xref: /titanic_51/usr/src/lib/libdscfg/common/cfg.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <stdio.h>
27*fcf3ce44SJohn Forte 
28*fcf3ce44SJohn Forte #include <sys/types.h>
29*fcf3ce44SJohn Forte #include <sys/wait.h>
30*fcf3ce44SJohn Forte #include <stdio.h>
31*fcf3ce44SJohn Forte #include <sys/mnttab.h>
32*fcf3ce44SJohn Forte #include <sys/vtoc.h>
33*fcf3ce44SJohn Forte #include <errno.h>
34*fcf3ce44SJohn Forte #include <limits.h>
35*fcf3ce44SJohn Forte #include <fcntl.h>
36*fcf3ce44SJohn Forte #include <string.h>
37*fcf3ce44SJohn Forte #include <stdarg.h>
38*fcf3ce44SJohn Forte #include <strings.h>
39*fcf3ce44SJohn Forte #include <stdlib.h>
40*fcf3ce44SJohn Forte #include <unistd.h>
41*fcf3ce44SJohn Forte #include <sys/mman.h>
42*fcf3ce44SJohn Forte #include <sys/stat.h>
43*fcf3ce44SJohn Forte 
44*fcf3ce44SJohn Forte #include <locale.h>
45*fcf3ce44SJohn Forte #include <langinfo.h>
46*fcf3ce44SJohn Forte #include <libintl.h>
47*fcf3ce44SJohn Forte #include <stdarg.h>
48*fcf3ce44SJohn Forte #include <netdb.h>
49*fcf3ce44SJohn Forte #include <ctype.h>
50*fcf3ce44SJohn Forte #include <sys/stat.h>
51*fcf3ce44SJohn Forte #include <sys/utsname.h>
52*fcf3ce44SJohn Forte 
53*fcf3ce44SJohn Forte #include "cfg_impl.h"
54*fcf3ce44SJohn Forte #include "cfg.h"
55*fcf3ce44SJohn Forte #include "cfg_lockd.h"
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte #if 0
58*fcf3ce44SJohn Forte #define	DEBUG_CFGLIST
59*fcf3ce44SJohn Forte #define	DEBUG_EXTRA
60*fcf3ce44SJohn Forte #define	DEBUG_LIB
61*fcf3ce44SJohn Forte #define	DEBUG_NOISY
62*fcf3ce44SJohn Forte #define	DEBUG_OUT
63*fcf3ce44SJohn Forte #endif
64*fcf3ce44SJohn Forte 
65*fcf3ce44SJohn Forte #define	MAX_CFG		16	/* Max. number of lines in /etc/dscfg_format */
66*fcf3ce44SJohn Forte #define	MAX_SET		12	/* number of chars in a set name */
67*fcf3ce44SJohn Forte 
68*fcf3ce44SJohn Forte 
69*fcf3ce44SJohn Forte /* parser tree for config section */
70*fcf3ce44SJohn Forte static struct parser chead[MAX_CFG] = { NULL };
71*fcf3ce44SJohn Forte static int chead_loaded = 0;
72*fcf3ce44SJohn Forte static char	config_file[CFG_MAX_BUF];
73*fcf3ce44SJohn Forte static char	dectohex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
74*fcf3ce44SJohn Forte 				'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
75*fcf3ce44SJohn Forte #define	CHARS_TO_ENCODE "=;\t "
76*fcf3ce44SJohn Forte #define	min(a, b) ((a) > (b) ? (b) : (a))
77*fcf3ce44SJohn Forte 
78*fcf3ce44SJohn Forte /* field to be sorted on in sorting routines */
79*fcf3ce44SJohn Forte static struct sortby_s {
80*fcf3ce44SJohn Forte 	char section[CFG_MAX_KEY];
81*fcf3ce44SJohn Forte 	char field[CFG_MAX_KEY];
82*fcf3ce44SJohn Forte 	int offset;
83*fcf3ce44SJohn Forte 	int comperror;
84*fcf3ce44SJohn Forte } sortby;
85*fcf3ce44SJohn Forte 
86*fcf3ce44SJohn Forte int	cfg_severity = 0;
87*fcf3ce44SJohn Forte char	*cfg_perror_str;
88*fcf3ce44SJohn Forte static int	cfg_read(cfp_t *);
89*fcf3ce44SJohn Forte static void	cfg_read_parser_config(cfp_t *);
90*fcf3ce44SJohn Forte static int	cfg_rdlock(CFGFILE *);
91*fcf3ce44SJohn Forte static int	cfg_wrlock(CFGFILE *);
92*fcf3ce44SJohn Forte static int	cfg_lockd;
93*fcf3ce44SJohn Forte void 		cfg_replace_lists(cfp_t *);
94*fcf3ce44SJohn Forte void		cfg_free_parser_tree();
95*fcf3ce44SJohn Forte void		cfg_invalidate_hsizes(int, const char *);
96*fcf3ce44SJohn Forte int		cfg_map_cfglists(cfp_t *);
97*fcf3ce44SJohn Forte int		cfg_hdrcmp(cfp_t *);
98*fcf3ce44SJohn Forte void		cfg_free_cfglist(cfp_t *);
99*fcf3ce44SJohn Forte 
100*fcf3ce44SJohn Forte extern cfg_io_t *cfg_block_io_provider(void);
101*fcf3ce44SJohn Forte extern cfg_io_t *cfg_raw_io_provider(void);
102*fcf3ce44SJohn Forte extern int cl_initialized;
103*fcf3ce44SJohn Forte 
104*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
105*fcf3ce44SJohn Forte static void
106*fcf3ce44SJohn Forte dump_status(cfp_t *cfp, char *str)
107*fcf3ce44SJohn Forte {
108*fcf3ce44SJohn Forte 	printf("called from %s\n", str);
109*fcf3ce44SJohn Forte 	printf(gettext("Header info:\n"
110*fcf3ce44SJohn Forte 		"\tmagic: %x\tstate: %x\n"),
111*fcf3ce44SJohn Forte 		cfp->cf_head->h_magic, cfp->cf_head->h_state);
112*fcf3ce44SJohn Forte 	printf(gettext("Parser section:\n"
113*fcf3ce44SJohn Forte 		"Start: %x\tsize: %d\toffset: %d\n"),
114*fcf3ce44SJohn Forte 		cfp->cf_mapped, cfp->cf_head->h_parsesize,
115*fcf3ce44SJohn Forte 		cfp->cf_head->h_parseoff);
116*fcf3ce44SJohn Forte 	printf(gettext("Config section:\n"
117*fcf3ce44SJohn Forte 		"Start: %x\tsize:%d\tacsize: %d\n"),
118*fcf3ce44SJohn Forte 		cfp->cf_head->h_cparse, cfp->cf_head->h_csize,
119*fcf3ce44SJohn Forte 		cfp->cf_head->h_acsize);
120*fcf3ce44SJohn Forte 	printf("\n\tccopy1: %x\tccopy2: %x\n",
121*fcf3ce44SJohn Forte 		cfp->cf_head->h_ccopy1, cfp->cf_head->h_ccopy2);
122*fcf3ce44SJohn Forte 	printf(gettext("Sequence:\n"
123*fcf3ce44SJohn Forte 		"\tseq1: %d\t\tseq2: %d\n"),
124*fcf3ce44SJohn Forte 		cfp->cf_head->h_seq1, cfp->cf_head->h_seq2);
125*fcf3ce44SJohn Forte }
126*fcf3ce44SJohn Forte #endif /* DEBUG */
127*fcf3ce44SJohn Forte 
128*fcf3ce44SJohn Forte /*
129*fcf3ce44SJohn Forte  * cfg_get_item
130*fcf3ce44SJohn Forte  * return position from parser config given tag and field
131*fcf3ce44SJohn Forte  */
132*fcf3ce44SJohn Forte static int
133*fcf3ce44SJohn Forte cfg_get_item(struct parser *tbl, const char *tag, const char *field)
134*fcf3ce44SJohn Forte {
135*fcf3ce44SJohn Forte 	int i;
136*fcf3ce44SJohn Forte 	struct lookup *p;
137*fcf3ce44SJohn Forte 
138*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_CFG; i++) {
139*fcf3ce44SJohn Forte 		/* only as many lists as defined */
140*fcf3ce44SJohn Forte 		if (tbl[i].tag.l_word[0] == '\0') {
141*fcf3ce44SJohn Forte 			i = MAX_CFG;
142*fcf3ce44SJohn Forte 			break;
143*fcf3ce44SJohn Forte 		}
144*fcf3ce44SJohn Forte 		if (strcmp(tbl[i].tag.l_word, tag) == 0)
145*fcf3ce44SJohn Forte 			break;
146*fcf3ce44SJohn Forte 	}
147*fcf3ce44SJohn Forte 
148*fcf3ce44SJohn Forte 	/* Handle table size */
149*fcf3ce44SJohn Forte 	if (i < MAX_CFG) {
150*fcf3ce44SJohn Forte 		p = tbl[i].fld;
151*fcf3ce44SJohn Forte 		while (p) {
152*fcf3ce44SJohn Forte 			if (strcmp(p->l_word, field) == 0)
153*fcf3ce44SJohn Forte 				return (p->l_value);
154*fcf3ce44SJohn Forte 			p = p->l_next;
155*fcf3ce44SJohn Forte 		}
156*fcf3ce44SJohn Forte 	}
157*fcf3ce44SJohn Forte 
158*fcf3ce44SJohn Forte 	/* Handle failure */
159*fcf3ce44SJohn Forte 	return (-1);
160*fcf3ce44SJohn Forte }
161*fcf3ce44SJohn Forte 
162*fcf3ce44SJohn Forte /*
163*fcf3ce44SJohn Forte  * cfg_get_num_flds
164*fcf3ce44SJohn Forte  * return number of fields for given parser tag
165*fcf3ce44SJohn Forte  */
166*fcf3ce44SJohn Forte static int
167*fcf3ce44SJohn Forte cfg_get_num_flds(struct parser *tbl, const char *tag, int *table_index)
168*fcf3ce44SJohn Forte {
169*fcf3ce44SJohn Forte 	int i;
170*fcf3ce44SJohn Forte 	int pos = 0;
171*fcf3ce44SJohn Forte 	struct lookup *p;
172*fcf3ce44SJohn Forte 
173*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_CFG; i++) {
174*fcf3ce44SJohn Forte 		/* only as many lists as defined */
175*fcf3ce44SJohn Forte 		if (tbl[i].tag.l_word[0] == '\0') {
176*fcf3ce44SJohn Forte 			i = MAX_CFG;
177*fcf3ce44SJohn Forte 			break;
178*fcf3ce44SJohn Forte 		}
179*fcf3ce44SJohn Forte 		if (strcmp(tbl[i].tag.l_word, tag) == 0) {
180*fcf3ce44SJohn Forte 			*table_index = i;
181*fcf3ce44SJohn Forte 			break;
182*fcf3ce44SJohn Forte 		}
183*fcf3ce44SJohn Forte 	}
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte 	/* Handle table size */
186*fcf3ce44SJohn Forte 	if (i < MAX_CFG) {
187*fcf3ce44SJohn Forte 		p = tbl[i].fld;
188*fcf3ce44SJohn Forte 		while (p) {
189*fcf3ce44SJohn Forte 			pos++;
190*fcf3ce44SJohn Forte 			p = p->l_next;
191*fcf3ce44SJohn Forte 		}
192*fcf3ce44SJohn Forte 		return (pos);
193*fcf3ce44SJohn Forte 	}
194*fcf3ce44SJohn Forte 
195*fcf3ce44SJohn Forte 	return (0);
196*fcf3ce44SJohn Forte }
197*fcf3ce44SJohn Forte 
198*fcf3ce44SJohn Forte /*
199*fcf3ce44SJohn Forte  * count white space fields
200*fcf3ce44SJohn Forte  */
201*fcf3ce44SJohn Forte static int
202*fcf3ce44SJohn Forte cfg_cnt_flds(char *value)
203*fcf3ce44SJohn Forte {
204*fcf3ce44SJohn Forte 	char *ptr;
205*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
206*fcf3ce44SJohn Forte 	int flds = 0;
207*fcf3ce44SJohn Forte 
208*fcf3ce44SJohn Forte 	if ((value == NULL) || (strlen(value) >= CFG_MAX_BUF))
209*fcf3ce44SJohn Forte 		return (0);
210*fcf3ce44SJohn Forte 
211*fcf3ce44SJohn Forte 	bzero(buf, CFG_MAX_BUF);
212*fcf3ce44SJohn Forte 	strcpy(buf, value);
213*fcf3ce44SJohn Forte 	ptr = strtok(buf, " ");
214*fcf3ce44SJohn Forte 	while (ptr) {
215*fcf3ce44SJohn Forte 		flds++;
216*fcf3ce44SJohn Forte 		ptr = strtok(NULL, " ");
217*fcf3ce44SJohn Forte 	}
218*fcf3ce44SJohn Forte 	return (flds);
219*fcf3ce44SJohn Forte }
220*fcf3ce44SJohn Forte 
221*fcf3ce44SJohn Forte /*
222*fcf3ce44SJohn Forte  * cfg_get_parser_offset
223*fcf3ce44SJohn Forte  * returns the index for each
224*fcf3ce44SJohn Forte  * section of the parser..
225*fcf3ce44SJohn Forte  * ie. parser info for sndr is chead[3].tag.l_word
226*fcf3ce44SJohn Forte  * this will help us find sndr quicker, as the
227*fcf3ce44SJohn Forte  * the memory picture of the sets mimic this ordering
228*fcf3ce44SJohn Forte  */
229*fcf3ce44SJohn Forte static int
230*fcf3ce44SJohn Forte cfg_get_parser_offset(const char *section)
231*fcf3ce44SJohn Forte {
232*fcf3ce44SJohn Forte 	int i;
233*fcf3ce44SJohn Forte 
234*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_CFG; i++) {
235*fcf3ce44SJohn Forte 		/* only as many lists as defined */
236*fcf3ce44SJohn Forte 		if (chead[i].tag.l_word[0] == '\0') {
237*fcf3ce44SJohn Forte 			i = MAX_CFG;
238*fcf3ce44SJohn Forte 			break;
239*fcf3ce44SJohn Forte 		}
240*fcf3ce44SJohn Forte 		if (strcmp(chead[i].tag.l_word, section) == 0)
241*fcf3ce44SJohn Forte 			break;
242*fcf3ce44SJohn Forte 	}
243*fcf3ce44SJohn Forte 
244*fcf3ce44SJohn Forte 	/* Handle table size */
245*fcf3ce44SJohn Forte 	if (i < MAX_CFG)
246*fcf3ce44SJohn Forte 		return (i);
247*fcf3ce44SJohn Forte 
248*fcf3ce44SJohn Forte 	/* Handle failure */
249*fcf3ce44SJohn Forte 	cfg_perror_str = dgettext("cfg",
250*fcf3ce44SJohn Forte 		"cfg_get_parser_offset: section not found");
251*fcf3ce44SJohn Forte 	cfg_severity = CFG_EFATAL;
252*fcf3ce44SJohn Forte 	errno = ESRCH;
253*fcf3ce44SJohn Forte 	return (-1);
254*fcf3ce44SJohn Forte }
255*fcf3ce44SJohn Forte 
256*fcf3ce44SJohn Forte /*
257*fcf3ce44SJohn Forte  * cfg_fld_mov
258*fcf3ce44SJohn Forte  * move fields from old buffer to new
259*fcf3ce44SJohn Forte  * moving only specified fields
260*fcf3ce44SJohn Forte  * concates newbuf
261*fcf3ce44SJohn Forte  * returns fields moved
262*fcf3ce44SJohn Forte  */
263*fcf3ce44SJohn Forte static int
264*fcf3ce44SJohn Forte cfg_fld_mov(char *newbuf, char *oldbuf, int start, int end)
265*fcf3ce44SJohn Forte {
266*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
267*fcf3ce44SJohn Forte 	char *ptr;
268*fcf3ce44SJohn Forte 	int flds = 0;
269*fcf3ce44SJohn Forte 
270*fcf3ce44SJohn Forte 	bzero(buf, CFG_MAX_BUF);
271*fcf3ce44SJohn Forte 	if (oldbuf == NULL)
272*fcf3ce44SJohn Forte 		return (0);
273*fcf3ce44SJohn Forte 
274*fcf3ce44SJohn Forte 	if ((start > end) || (strlen(oldbuf) >= CFG_MAX_BUF)) {
275*fcf3ce44SJohn Forte 		return (0);
276*fcf3ce44SJohn Forte 	}
277*fcf3ce44SJohn Forte 	if (!start || !end)
278*fcf3ce44SJohn Forte 		return (-1);
279*fcf3ce44SJohn Forte 	strcpy(buf, oldbuf);
280*fcf3ce44SJohn Forte 	ptr = strtok(buf, " ");
281*fcf3ce44SJohn Forte 	while (ptr) {
282*fcf3ce44SJohn Forte 		flds++;
283*fcf3ce44SJohn Forte 		if (flds >= start && flds <= end) {
284*fcf3ce44SJohn Forte 			strcat(newbuf, ptr);
285*fcf3ce44SJohn Forte 			strcat(newbuf, " ");
286*fcf3ce44SJohn Forte 		}
287*fcf3ce44SJohn Forte 		ptr = strtok(NULL, " ");
288*fcf3ce44SJohn Forte 	}
289*fcf3ce44SJohn Forte 
290*fcf3ce44SJohn Forte 	return (flds);
291*fcf3ce44SJohn Forte }
292*fcf3ce44SJohn Forte 
293*fcf3ce44SJohn Forte /*
294*fcf3ce44SJohn Forte  * cfg_filter_node
295*fcf3ce44SJohn Forte  * return indication if this raw buf should be returned
296*fcf3ce44SJohn Forte  * checks cfg->cf_node for filtering
297*fcf3ce44SJohn Forte  * We already know that this buf meets most of our criteria
298*fcf3ce44SJohn Forte  * find the cnode field in the buf and see if it matches
299*fcf3ce44SJohn Forte  * returns
300*fcf3ce44SJohn Forte  * 	TRUE	Good entry
301*fcf3ce44SJohn Forte  * 	FALSE	Don't use it
302*fcf3ce44SJohn Forte  */
303*fcf3ce44SJohn Forte static int
304*fcf3ce44SJohn Forte cfg_filter_node(CFGFILE *cfg, struct parser *tbl, char *buf, char *tag)
305*fcf3ce44SJohn Forte {
306*fcf3ce44SJohn Forte 	char tmpbuf[CFG_MAX_BUF];
307*fcf3ce44SJohn Forte 	int i = 1;
308*fcf3ce44SJohn Forte 	int fld;
309*fcf3ce44SJohn Forte 	char *ptr;
310*fcf3ce44SJohn Forte 
311*fcf3ce44SJohn Forte 	if (!cfg->cf_node)		/* no filter always good */
312*fcf3ce44SJohn Forte 		return (TRUE);
313*fcf3ce44SJohn Forte 	bzero(tmpbuf, CFG_MAX_BUF);
314*fcf3ce44SJohn Forte 	fld = cfg_get_item(tbl, tag, "cnode");
315*fcf3ce44SJohn Forte 	if (fld < 0)	/* no cnode field always good */
316*fcf3ce44SJohn Forte 		return (TRUE);
317*fcf3ce44SJohn Forte 	strncpy(tmpbuf, buf, CFG_MAX_BUF);
318*fcf3ce44SJohn Forte 	if (tmpbuf[CFG_MAX_BUF - 1] != '\0')
319*fcf3ce44SJohn Forte 		return (FALSE);
320*fcf3ce44SJohn Forte 	ptr = strtok(tmpbuf, " ");
321*fcf3ce44SJohn Forte 	while (ptr && (i < fld)) {
322*fcf3ce44SJohn Forte 		ptr = strtok(NULL, " ");
323*fcf3ce44SJohn Forte 		i++;
324*fcf3ce44SJohn Forte 	}
325*fcf3ce44SJohn Forte 	if (!ptr)
326*fcf3ce44SJohn Forte 		return (FALSE);
327*fcf3ce44SJohn Forte #ifdef DEBUG_EXTRA
328*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_filter_node: node=%s:%d cnode=%s:%d\n",
329*fcf3ce44SJohn Forte 	    cfg->cf_node, strlen(cfg->cf_node), ptr, strlen(ptr));
330*fcf3ce44SJohn Forte #endif
331*fcf3ce44SJohn Forte 	if (strcmp(ptr, cfg->cf_node) == 0)
332*fcf3ce44SJohn Forte 		return (TRUE);
333*fcf3ce44SJohn Forte 	return (FALSE);
334*fcf3ce44SJohn Forte }
335*fcf3ce44SJohn Forte /*
336*fcf3ce44SJohn Forte  * cfg_insert_node
337*fcf3ce44SJohn Forte  * insert resource in bufs which contain cnode parser field
338*fcf3ce44SJohn Forte  */
339*fcf3ce44SJohn Forte static void
340*fcf3ce44SJohn Forte cfg_insert_node(CFGFILE *cfg, struct parser *tbl, char *buf, char *tag)
341*fcf3ce44SJohn Forte {
342*fcf3ce44SJohn Forte 	char tmpbuf[CFG_MAX_BUF];
343*fcf3ce44SJohn Forte 	int fld;
344*fcf3ce44SJohn Forte 	int nflds;
345*fcf3ce44SJohn Forte 	int table_index;
346*fcf3ce44SJohn Forte 
347*fcf3ce44SJohn Forte 	bzero(tmpbuf, CFG_MAX_BUF);
348*fcf3ce44SJohn Forte 	strcpy(tmpbuf, " ");
349*fcf3ce44SJohn Forte 	fld = cfg_get_item(tbl, tag, "cnode");
350*fcf3ce44SJohn Forte 	nflds = cfg_get_num_flds(tbl, tag, &table_index);
351*fcf3ce44SJohn Forte 	if ((fld < 0) && !(cfg->cf_node))	/* no cnode field always good */
352*fcf3ce44SJohn Forte 		return;
353*fcf3ce44SJohn Forte 
354*fcf3ce44SJohn Forte 	cfg_fld_mov(tmpbuf, buf, 1, (fld - 1));
355*fcf3ce44SJohn Forte 	if (cfg->cf_node)
356*fcf3ce44SJohn Forte 		strcat(tmpbuf, cfg->cf_node);
357*fcf3ce44SJohn Forte 	else
358*fcf3ce44SJohn Forte 		strcat(tmpbuf, "-");
359*fcf3ce44SJohn Forte 	strcat(tmpbuf, " ");
360*fcf3ce44SJohn Forte 	cfg_fld_mov(tmpbuf, buf, (fld + 1), nflds);
361*fcf3ce44SJohn Forte 	bcopy(tmpbuf, buf, strlen(tmpbuf) + 1);
362*fcf3ce44SJohn Forte }
363*fcf3ce44SJohn Forte 
364*fcf3ce44SJohn Forte /*
365*fcf3ce44SJohn Forte  * cfg_is_cnode
366*fcf3ce44SJohn Forte  * Parser current buffer to see if a non-empty " - " cnode exists
367*fcf3ce44SJohn Forte  */
368*fcf3ce44SJohn Forte /*ARGSUSED*/
369*fcf3ce44SJohn Forte static int
370*fcf3ce44SJohn Forte cfg_is_cnode(CFGFILE *cfg, struct parser *tbl, char *buf, char *tag)
371*fcf3ce44SJohn Forte {
372*fcf3ce44SJohn Forte 	char tmpbuf[CFG_MAX_BUF];
373*fcf3ce44SJohn Forte 	int fld = cfg_get_item(tbl, tag, "cnode");
374*fcf3ce44SJohn Forte 
375*fcf3ce44SJohn Forte 	if (fld >= 0) {
376*fcf3ce44SJohn Forte 		tmpbuf[0] = '\0';
377*fcf3ce44SJohn Forte 		cfg_fld_mov(tmpbuf, buf, fld, fld);
378*fcf3ce44SJohn Forte 		return (strcmp(tmpbuf, "- ") ? TRUE : FALSE);
379*fcf3ce44SJohn Forte 	}
380*fcf3ce44SJohn Forte 	return (FALSE);
381*fcf3ce44SJohn Forte }
382*fcf3ce44SJohn Forte /*
383*fcf3ce44SJohn Forte  * cfg_get_cstring
384*fcf3ce44SJohn Forte  * key determines section and value
385*fcf3ce44SJohn Forte  * special considerations:
386*fcf3ce44SJohn Forte  * AA.BB.CC...
387*fcf3ce44SJohn Forte  * AA = data service tag
388*fcf3ce44SJohn Forte  * BB = set number relative to first set (1..n)
389*fcf3ce44SJohn Forte  * CC = field of set or if absent, all
390*fcf3ce44SJohn Forte  */
391*fcf3ce44SJohn Forte int
392*fcf3ce44SJohn Forte cfg_get_cstring(CFGFILE *cfg, const char *key, void *value, int value_len)
393*fcf3ce44SJohn Forte {
394*fcf3ce44SJohn Forte 	cfp_t *cfp;
395*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
396*fcf3ce44SJohn Forte 	char tmpkey[CFG_MAX_KEY];
397*fcf3ce44SJohn Forte 	char *section;
398*fcf3ce44SJohn Forte 	char set[MAX_SET];
399*fcf3ce44SJohn Forte 	char *setp;
400*fcf3ce44SJohn Forte 	char *itemp;
401*fcf3ce44SJohn Forte 	char *p;
402*fcf3ce44SJohn Forte 	int pos = 1;
403*fcf3ce44SJohn Forte 	int setnum;
404*fcf3ce44SJohn Forte 	int relnum;
405*fcf3ce44SJohn Forte 	int secnum;
406*fcf3ce44SJohn Forte 	int numfound;
407*fcf3ce44SJohn Forte 	int needed;
408*fcf3ce44SJohn Forte 	int table_offset;
409*fcf3ce44SJohn Forte 
410*fcf3ce44SJohn Forte 	if (cfg == NULL) {
411*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
412*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
413*fcf3ce44SJohn Forte 		return (-1);
414*fcf3ce44SJohn Forte 	}
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 	if (!cfg_rdlock(cfg)) {
417*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_NOTLOCKED);
418*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
419*fcf3ce44SJohn Forte 		return (-1);
420*fcf3ce44SJohn Forte 	}
421*fcf3ce44SJohn Forte 
422*fcf3ce44SJohn Forte 	bzero(buf, sizeof (buf));
423*fcf3ce44SJohn Forte 	bzero(set, sizeof (set));
424*fcf3ce44SJohn Forte 	bzero(tmpkey, sizeof (tmpkey));
425*fcf3ce44SJohn Forte 	strcpy(tmpkey, key);
426*fcf3ce44SJohn Forte 	section = strtok(tmpkey, ".");
427*fcf3ce44SJohn Forte 	setp = strtok(NULL, ".");
428*fcf3ce44SJohn Forte 	itemp = strtok(NULL, ".");
429*fcf3ce44SJohn Forte 
430*fcf3ce44SJohn Forte #ifdef DEBUG_EXTRA
431*fcf3ce44SJohn Forte 	if (!itemp)
432*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg_get_cstring:section:%s setp=%s\n",
433*fcf3ce44SJohn Forte 		    section, setp);
434*fcf3ce44SJohn Forte 	else
435*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
436*fcf3ce44SJohn Forte 		    "cfg_get_cstring:section:%s setp=%s fld=%s\n",
437*fcf3ce44SJohn Forte 		    section, setp, itemp);
438*fcf3ce44SJohn Forte #endif
439*fcf3ce44SJohn Forte 
440*fcf3ce44SJohn Forte 	table_offset = cfg_get_parser_offset(section);
441*fcf3ce44SJohn Forte 	setnum = atoi(setp + 3);
442*fcf3ce44SJohn Forte 	if ((setnum < 1) || (setnum > 0x7ffd)) {
443*fcf3ce44SJohn Forte 		errno = EINVAL;
444*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
445*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
446*fcf3ce44SJohn Forte 		return (-1);
447*fcf3ce44SJohn Forte 	}
448*fcf3ce44SJohn Forte 
449*fcf3ce44SJohn Forte 	/*
450*fcf3ce44SJohn Forte 	 * we have to figure out where this set is
451*fcf3ce44SJohn Forte 	 * in relation to other sets
452*fcf3ce44SJohn Forte 	 */
453*fcf3ce44SJohn Forte 	relnum = 1;
454*fcf3ce44SJohn Forte 	secnum = 0;
455*fcf3ce44SJohn Forte 	numfound = 0;
456*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
457*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
458*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
459*fcf3ce44SJohn Forte 			if (!cfg_read(cfp)) {
460*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
461*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
462*fcf3ce44SJohn Forte 				return (-1);
463*fcf3ce44SJohn Forte 			}
464*fcf3ce44SJohn Forte 		}
465*fcf3ce44SJohn Forte 		while (numfound < setnum) {
466*fcf3ce44SJohn Forte 			if ((*cfp->cf_pp->readcf)
467*fcf3ce44SJohn Forte 			    (cfp, buf, table_offset, relnum - secnum) == NULL) {
468*fcf3ce44SJohn Forte 				secnum = relnum - 1;
469*fcf3ce44SJohn Forte 				break;
470*fcf3ce44SJohn Forte 			}
471*fcf3ce44SJohn Forte 			if (cfg_filter_node(cfg, &chead[0], buf, section))
472*fcf3ce44SJohn Forte 				numfound++;
473*fcf3ce44SJohn Forte 
474*fcf3ce44SJohn Forte 			if (numfound == setnum)
475*fcf3ce44SJohn Forte 				break;
476*fcf3ce44SJohn Forte 
477*fcf3ce44SJohn Forte 			relnum++;
478*fcf3ce44SJohn Forte 		}
479*fcf3ce44SJohn Forte 		if (numfound == setnum)
480*fcf3ce44SJohn Forte 			break;
481*fcf3ce44SJohn Forte 	}
482*fcf3ce44SJohn Forte 
483*fcf3ce44SJohn Forte 	/* Fail to find anything? */
484*fcf3ce44SJohn Forte 	if (cfp >= &cfg->cf[2]) {
485*fcf3ce44SJohn Forte 		errno = ESRCH;
486*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", strerror(errno));
487*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
488*fcf3ce44SJohn Forte 		return (-1);
489*fcf3ce44SJohn Forte 	}
490*fcf3ce44SJohn Forte 
491*fcf3ce44SJohn Forte 	if (buf) {
492*fcf3ce44SJohn Forte 		if (!itemp) {
493*fcf3ce44SJohn Forte 			strncpy(value, buf, value_len);
494*fcf3ce44SJohn Forte 			return (0);
495*fcf3ce44SJohn Forte 		}
496*fcf3ce44SJohn Forte 
497*fcf3ce44SJohn Forte 		if (itemp) {
498*fcf3ce44SJohn Forte 			needed = cfg_get_item(&chead[0], section, itemp);
499*fcf3ce44SJohn Forte 			p = strtok(buf, " ");
500*fcf3ce44SJohn Forte 			while (p) {
501*fcf3ce44SJohn Forte 				if (needed == pos) {
502*fcf3ce44SJohn Forte 					errno = 0;
503*fcf3ce44SJohn Forte 					if (*p == '-') {
504*fcf3ce44SJohn Forte 						strcpy(value, "");
505*fcf3ce44SJohn Forte 						return (0);
506*fcf3ce44SJohn Forte 					}
507*fcf3ce44SJohn Forte 					else
508*fcf3ce44SJohn Forte 						if (strlen(p) > value_len) {
509*fcf3ce44SJohn Forte 							errno = E2BIG;
510*fcf3ce44SJohn Forte 							cfg_perror_str =
511*fcf3ce44SJohn Forte 							dgettext("cfg",
512*fcf3ce44SJohn Forte 							strerror(errno));
513*fcf3ce44SJohn Forte 							cfg_severity =
514*fcf3ce44SJohn Forte 							CFG_ENONFATAL;
515*fcf3ce44SJohn Forte 							return (-1);
516*fcf3ce44SJohn Forte 						}
517*fcf3ce44SJohn Forte 
518*fcf3ce44SJohn Forte 						strncpy(value, p, value_len);
519*fcf3ce44SJohn Forte 
520*fcf3ce44SJohn Forte 					return (pos);
521*fcf3ce44SJohn Forte 				}
522*fcf3ce44SJohn Forte 				p = strtok(NULL, " ");
523*fcf3ce44SJohn Forte 				if (!p)
524*fcf3ce44SJohn Forte 					break;
525*fcf3ce44SJohn Forte 				pos++;
526*fcf3ce44SJohn Forte 			}
527*fcf3ce44SJohn Forte 		}
528*fcf3ce44SJohn Forte 	}
529*fcf3ce44SJohn Forte 	errno = ESRCH;
530*fcf3ce44SJohn Forte 	cfg_perror_str = dgettext("cfg", strerror(errno));
531*fcf3ce44SJohn Forte 	cfg_severity = CFG_ENONFATAL;
532*fcf3ce44SJohn Forte 	return (-1);
533*fcf3ce44SJohn Forte }
534*fcf3ce44SJohn Forte 
535*fcf3ce44SJohn Forte /*
536*fcf3ce44SJohn Forte  * cfg_find_cstring()
537*fcf3ce44SJohn Forte  * search for a string in the specified section
538*fcf3ce44SJohn Forte  * in the specified field(s)
539*fcf3ce44SJohn Forte  * if nfld is 0, then the string is searched for in
540*fcf3ce44SJohn Forte  * every field of the entry
541*fcf3ce44SJohn Forte  * the set number of the first occurence of target is returned
542*fcf3ce44SJohn Forte  * ie. if /dev/vx/rdsk/vol10 is found in sndr.set9, 9 will be returned
543*fcf3ce44SJohn Forte  * that is, of course, if the correct field was searched on.
544*fcf3ce44SJohn Forte  * -1 on error
545*fcf3ce44SJohn Forte  *
546*fcf3ce44SJohn Forte  */
547*fcf3ce44SJohn Forte int
548*fcf3ce44SJohn Forte cfg_find_cstring(CFGFILE *cfg, const char *target,
549*fcf3ce44SJohn Forte     const char *section, int numflds, ...) {
550*fcf3ce44SJohn Forte 
551*fcf3ce44SJohn Forte 	char **list = NULL;
552*fcf3ce44SJohn Forte 	va_list ap;
553*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
554*fcf3ce44SJohn Forte 	char *field, *p;
555*fcf3ce44SJohn Forte 	char **fldbuf = NULL;
556*fcf3ce44SJohn Forte 	int i, j, rc;
557*fcf3ce44SJohn Forte 	int pos = 1;
558*fcf3ce44SJohn Forte 	int fieldnum;
559*fcf3ce44SJohn Forte 	int nflds;
560*fcf3ce44SJohn Forte 	int tbl_off;
561*fcf3ce44SJohn Forte 
562*fcf3ce44SJohn Forte 	if (cfg == NULL) {
563*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
564*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
565*fcf3ce44SJohn Forte 		return (-1);
566*fcf3ce44SJohn Forte 	}
567*fcf3ce44SJohn Forte 
568*fcf3ce44SJohn Forte 	if (numflds == 0) {
569*fcf3ce44SJohn Forte 		nflds = cfg_get_num_flds(&chead[0], section, &tbl_off);
570*fcf3ce44SJohn Forte 
571*fcf3ce44SJohn Forte 	} else {
572*fcf3ce44SJohn Forte 		nflds = numflds;
573*fcf3ce44SJohn Forte 	}
574*fcf3ce44SJohn Forte 	if ((fldbuf = calloc(nflds, CFG_MAX_KEY)) == NULL) {
575*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", strerror(errno));
576*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
577*fcf3ce44SJohn Forte 		return (-1);
578*fcf3ce44SJohn Forte 	}
579*fcf3ce44SJohn Forte 
580*fcf3ce44SJohn Forte 	if (numflds == 0) { /* search the whole string */
581*fcf3ce44SJohn Forte 		if ((rc = cfg_get_section(cfg, &list, section)) <= 0) {
582*fcf3ce44SJohn Forte 			for (i = 0; i < nflds; i++)
583*fcf3ce44SJohn Forte 				free(fldbuf[i]);
584*fcf3ce44SJohn Forte 			free(fldbuf);
585*fcf3ce44SJohn Forte 			return (rc);
586*fcf3ce44SJohn Forte 		}
587*fcf3ce44SJohn Forte 		for (i = 0; i < rc; i++) {
588*fcf3ce44SJohn Forte 			bzero(buf, sizeof (buf));
589*fcf3ce44SJohn Forte 			strcpy(buf, list[i]);
590*fcf3ce44SJohn Forte 			p = strtok(buf, " ");
591*fcf3ce44SJohn Forte 			while (p) {
592*fcf3ce44SJohn Forte 				if (strcmp(p, target) == 0) { /* we found it! */
593*fcf3ce44SJohn Forte 					for (j = 0; j < rc; j++)
594*fcf3ce44SJohn Forte 						free(list[j]);
595*fcf3ce44SJohn Forte 					free(list);
596*fcf3ce44SJohn Forte 					for (j = 0; j < nflds; j++)
597*fcf3ce44SJohn Forte 						free(fldbuf[j]);
598*fcf3ce44SJohn Forte 					free(fldbuf);
599*fcf3ce44SJohn Forte 					return (i + 1);
600*fcf3ce44SJohn Forte 				}
601*fcf3ce44SJohn Forte 			p = strtok(NULL, " ");
602*fcf3ce44SJohn Forte 			}
603*fcf3ce44SJohn Forte 		}
604*fcf3ce44SJohn Forte 		for (i = 0; i < nflds; i++)
605*fcf3ce44SJohn Forte 			free(fldbuf[j]);
606*fcf3ce44SJohn Forte 		for (i = 0; i < rc; i++)
607*fcf3ce44SJohn Forte 			free(list[i]);
608*fcf3ce44SJohn Forte 		free(fldbuf);
609*fcf3ce44SJohn Forte 		free(list);
610*fcf3ce44SJohn Forte 		return (0);
611*fcf3ce44SJohn Forte 	}
612*fcf3ce44SJohn Forte 
613*fcf3ce44SJohn Forte 	if ((rc = cfg_get_section(cfg, &list, section)) <= 0) {
614*fcf3ce44SJohn Forte 		for (i = 0; i < nflds; i++)
615*fcf3ce44SJohn Forte 			free(fldbuf[i]);
616*fcf3ce44SJohn Forte 		free(fldbuf);
617*fcf3ce44SJohn Forte 		return (rc);
618*fcf3ce44SJohn Forte 	}
619*fcf3ce44SJohn Forte 
620*fcf3ce44SJohn Forte 	va_start(ap, numflds);
621*fcf3ce44SJohn Forte 	for (i = 0; i < numflds; i++) {
622*fcf3ce44SJohn Forte 		fldbuf[i] = strdup(va_arg(ap, char *));
623*fcf3ce44SJohn Forte 	}
624*fcf3ce44SJohn Forte 
625*fcf3ce44SJohn Forte 	fldbuf[i] = NULL;
626*fcf3ce44SJohn Forte 
627*fcf3ce44SJohn Forte 	for (j = 0; j < numflds; j++) {
628*fcf3ce44SJohn Forte 		fieldnum = cfg_get_item(&chead[0], section, fldbuf[j]);
629*fcf3ce44SJohn Forte 		for (i = 0; i < rc; i++) {
630*fcf3ce44SJohn Forte 			bzero(buf, sizeof (buf));
631*fcf3ce44SJohn Forte 			strcpy(buf, list[i]);
632*fcf3ce44SJohn Forte 
633*fcf3ce44SJohn Forte 			field = strtok(buf, " ");
634*fcf3ce44SJohn Forte 			pos = 1;
635*fcf3ce44SJohn Forte 			while (pos < fieldnum) {
636*fcf3ce44SJohn Forte 				field = strtok(NULL, " ");
637*fcf3ce44SJohn Forte 				pos++;
638*fcf3ce44SJohn Forte 			}
639*fcf3ce44SJohn Forte 			if (field == NULL) {
640*fcf3ce44SJohn Forte 				for (j = 0; j < numflds; j++)
641*fcf3ce44SJohn Forte 					free(fldbuf[j]);
642*fcf3ce44SJohn Forte 				for (j = 0; j < rc; j++)
643*fcf3ce44SJohn Forte 					free(list[j]);
644*fcf3ce44SJohn Forte 				free(fldbuf);
645*fcf3ce44SJohn Forte 				free(list);
646*fcf3ce44SJohn Forte 				return (-1);
647*fcf3ce44SJohn Forte 			}
648*fcf3ce44SJohn Forte 
649*fcf3ce44SJohn Forte 			if (strcmp(field, target) == 0) {
650*fcf3ce44SJohn Forte 				for (j = 0; j < numflds; j++)
651*fcf3ce44SJohn Forte 					free(fldbuf[j]);
652*fcf3ce44SJohn Forte 				for (j = 0; j < rc; j++)
653*fcf3ce44SJohn Forte 					free(list[j]);
654*fcf3ce44SJohn Forte 				free(fldbuf);
655*fcf3ce44SJohn Forte 				free(list);
656*fcf3ce44SJohn Forte 
657*fcf3ce44SJohn Forte 				return (i + 1);
658*fcf3ce44SJohn Forte 			}
659*fcf3ce44SJohn Forte 
660*fcf3ce44SJohn Forte 		}
661*fcf3ce44SJohn Forte 
662*fcf3ce44SJohn Forte 	}
663*fcf3ce44SJohn Forte 	for (i = 0; i < nflds; i++)
664*fcf3ce44SJohn Forte 		free(fldbuf[i]);
665*fcf3ce44SJohn Forte 	for (i = 0; i < rc; i++)
666*fcf3ce44SJohn Forte 		free(list[i]);
667*fcf3ce44SJohn Forte 	free(fldbuf);
668*fcf3ce44SJohn Forte 	free(list);
669*fcf3ce44SJohn Forte 	return (0);
670*fcf3ce44SJohn Forte }
671*fcf3ce44SJohn Forte 
672*fcf3ce44SJohn Forte /*
673*fcf3ce44SJohn Forte  * cfg_put_cstring
674*fcf3ce44SJohn Forte  * modify entry or add an entry to configuration section
675*fcf3ce44SJohn Forte  * Key syntax supported
676*fcf3ce44SJohn Forte  *	tag		Add entry (in entirely) to config
677*fcf3ce44SJohn Forte  * 	tag.setn	Add entry to setn If it exists overwrite old entry
678*fcf3ce44SJohn Forte  * 	tag.setn.field	Change field in setn
679*fcf3ce44SJohn Forte  * value
680*fcf3ce44SJohn Forte  *	string to change
681*fcf3ce44SJohn Forte  *	NULL	delete specified key
682*fcf3ce44SJohn Forte  *
683*fcf3ce44SJohn Forte  */
684*fcf3ce44SJohn Forte 
685*fcf3ce44SJohn Forte int
686*fcf3ce44SJohn Forte cfg_put_cstring(CFGFILE *cfg, const char *key,  void *value, int val_len)
687*fcf3ce44SJohn Forte {
688*fcf3ce44SJohn Forte 	cfp_t *cfp;
689*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
690*fcf3ce44SJohn Forte 	char newbuf[CFG_MAX_BUF];
691*fcf3ce44SJohn Forte 	char *bufp;
692*fcf3ce44SJohn Forte 	char tmpkey[CFG_MAX_KEY];
693*fcf3ce44SJohn Forte 	char *section;
694*fcf3ce44SJohn Forte 	char *setp;
695*fcf3ce44SJohn Forte 	char *itemp;
696*fcf3ce44SJohn Forte 	int nofield = 0;
697*fcf3ce44SJohn Forte 	int noset = 0;
698*fcf3ce44SJohn Forte 	int fldnum;
699*fcf3ce44SJohn Forte 	int setnum = 0;
700*fcf3ce44SJohn Forte 	int relnum;
701*fcf3ce44SJohn Forte 	int secnum;
702*fcf3ce44SJohn Forte 	int numfound;
703*fcf3ce44SJohn Forte 	int addcnode = 1;
704*fcf3ce44SJohn Forte 	int table_index;
705*fcf3ce44SJohn Forte 	int table_offset;
706*fcf3ce44SJohn Forte 
707*fcf3ce44SJohn Forte 	if (cfg == NULL) {
708*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
709*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
710*fcf3ce44SJohn Forte 		return (-1);
711*fcf3ce44SJohn Forte 	}
712*fcf3ce44SJohn Forte 
713*fcf3ce44SJohn Forte 	bzero(buf, sizeof (buf));
714*fcf3ce44SJohn Forte 	strcpy(tmpkey, key);
715*fcf3ce44SJohn Forte 	section = strtok(tmpkey, ".");
716*fcf3ce44SJohn Forte 	setp = strtok(NULL, ".");
717*fcf3ce44SJohn Forte 	itemp = strtok(NULL, ".");
718*fcf3ce44SJohn Forte 
719*fcf3ce44SJohn Forte 	if (!cfg_wrlock(cfg)) {
720*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
721*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
722*fcf3ce44SJohn Forte 		return (-1);
723*fcf3ce44SJohn Forte 	}
724*fcf3ce44SJohn Forte 
725*fcf3ce44SJohn Forte 	if (!key) {
726*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
727*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
728*fcf3ce44SJohn Forte 		return (-1);
729*fcf3ce44SJohn Forte 	}
730*fcf3ce44SJohn Forte 	if (value && val_len == 0) {
731*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
732*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
733*fcf3ce44SJohn Forte 		return (-1);
734*fcf3ce44SJohn Forte 	}
735*fcf3ce44SJohn Forte 	if (!itemp)
736*fcf3ce44SJohn Forte 		nofield++;
737*fcf3ce44SJohn Forte 	if (!setp)
738*fcf3ce44SJohn Forte 		noset++;
739*fcf3ce44SJohn Forte 	else if (setp) {
740*fcf3ce44SJohn Forte 		setnum = atoi(setp + 3);
741*fcf3ce44SJohn Forte 		if (setnum < 1 || setnum > 0x7ffd) {
742*fcf3ce44SJohn Forte 			errno = EINVAL;
743*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", CFG_EINVAL);
744*fcf3ce44SJohn Forte 			cfg_severity = CFG_ENONFATAL;
745*fcf3ce44SJohn Forte 			return (-1);
746*fcf3ce44SJohn Forte 		}
747*fcf3ce44SJohn Forte 	}
748*fcf3ce44SJohn Forte 
749*fcf3ce44SJohn Forte 	table_offset = cfg_get_parser_offset(section);
750*fcf3ce44SJohn Forte 
751*fcf3ce44SJohn Forte 	/*
752*fcf3ce44SJohn Forte 	 * we have to figure out where this set is
753*fcf3ce44SJohn Forte 	 * in relation to other sets
754*fcf3ce44SJohn Forte 	 */
755*fcf3ce44SJohn Forte 	relnum = 1;
756*fcf3ce44SJohn Forte 	secnum = 0;
757*fcf3ce44SJohn Forte 	numfound = 0;
758*fcf3ce44SJohn Forte 
759*fcf3ce44SJohn Forte 	if (setp && nofield) {
760*fcf3ce44SJohn Forte 		char tmpbuf[CFG_MAX_BUF];
761*fcf3ce44SJohn Forte 		int rc;
762*fcf3ce44SJohn Forte 		int nflds;
763*fcf3ce44SJohn Forte 		int got;
764*fcf3ce44SJohn Forte 
765*fcf3ce44SJohn Forte 		/*
766*fcf3ce44SJohn Forte 		 * Set specified but no field
767*fcf3ce44SJohn Forte 		 */
768*fcf3ce44SJohn Forte 		for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
769*fcf3ce44SJohn Forte 			if (!cfp->cf_fd) continue;
770*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
771*fcf3ce44SJohn Forte 				if (!cfg_read(cfp)) {
772*fcf3ce44SJohn Forte 					cfg_perror_str =
773*fcf3ce44SJohn Forte 						dgettext("cfg", CFG_RDFAILED);
774*fcf3ce44SJohn Forte 					cfg_severity = CFG_EFATAL;
775*fcf3ce44SJohn Forte 					return (-1);
776*fcf3ce44SJohn Forte 				}
777*fcf3ce44SJohn Forte 			}
778*fcf3ce44SJohn Forte 			while (numfound < setnum) {
779*fcf3ce44SJohn Forte 				if ((*cfp->cf_pp->readcf)
780*fcf3ce44SJohn Forte 				    (cfp, tmpbuf, table_offset, relnum - secnum)
781*fcf3ce44SJohn Forte 				    == NULL) {
782*fcf3ce44SJohn Forte 					secnum = relnum - 1;
783*fcf3ce44SJohn Forte 					break;
784*fcf3ce44SJohn Forte 				}
785*fcf3ce44SJohn Forte 				if (cfg_filter_node(cfg, &chead[0], tmpbuf,
786*fcf3ce44SJohn Forte 					section))
787*fcf3ce44SJohn Forte 					numfound++;
788*fcf3ce44SJohn Forte 
789*fcf3ce44SJohn Forte 				if (numfound == setnum)
790*fcf3ce44SJohn Forte 					break;
791*fcf3ce44SJohn Forte 
792*fcf3ce44SJohn Forte 				relnum++;
793*fcf3ce44SJohn Forte 			}
794*fcf3ce44SJohn Forte 			if (numfound == setnum)
795*fcf3ce44SJohn Forte 				break;
796*fcf3ce44SJohn Forte 		}
797*fcf3ce44SJohn Forte 
798*fcf3ce44SJohn Forte 		/* Fail to find anything? */
799*fcf3ce44SJohn Forte 		if (cfp >= &cfg->cf[2]) {
800*fcf3ce44SJohn Forte 			errno = ESRCH;
801*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", strerror(errno));
802*fcf3ce44SJohn Forte 			cfg_severity = CFG_ENONFATAL;
803*fcf3ce44SJohn Forte 			return (-1);
804*fcf3ce44SJohn Forte 		}
805*fcf3ce44SJohn Forte 
806*fcf3ce44SJohn Forte 		nflds = cfg_get_num_flds(&chead[0], section, &table_index);
807*fcf3ce44SJohn Forte 
808*fcf3ce44SJohn Forte 		if (value == NULL) {
809*fcf3ce44SJohn Forte 			/* Remove entry completely */
810*fcf3ce44SJohn Forte 
811*fcf3ce44SJohn Forte 			if ((rc = ((*cfp->cf_pp->remcf)
812*fcf3ce44SJohn Forte 				    (cfp, table_index, relnum - secnum))) < 0)
813*fcf3ce44SJohn Forte 				return (rc);
814*fcf3ce44SJohn Forte 			return (0);
815*fcf3ce44SJohn Forte 		}
816*fcf3ce44SJohn Forte 
817*fcf3ce44SJohn Forte 		got = cfg_cnt_flds(value);
818*fcf3ce44SJohn Forte 		bzero(buf, sizeof (buf));
819*fcf3ce44SJohn Forte 
820*fcf3ce44SJohn Forte 		strncpy(buf, " ", 1);
821*fcf3ce44SJohn Forte 		if (strlen(value) > sizeof (buf) - 2) {
822*fcf3ce44SJohn Forte 			errno = E2BIG;
823*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", strerror(errno));
824*fcf3ce44SJohn Forte 			cfg_severity = CFG_ENONFATAL;
825*fcf3ce44SJohn Forte 			return (-1);
826*fcf3ce44SJohn Forte 		}
827*fcf3ce44SJohn Forte 		strncat(buf, value, val_len);
828*fcf3ce44SJohn Forte 		if (got < nflds) {
829*fcf3ce44SJohn Forte 			for (/* CSTYLED */; got < nflds; got++)
830*fcf3ce44SJohn Forte 				strncat(buf, " - ", 3);
831*fcf3ce44SJohn Forte 		} else if (got > nflds) {
832*fcf3ce44SJohn Forte 			return (-1);
833*fcf3ce44SJohn Forte 		} else {
834*fcf3ce44SJohn Forte 			/* got == nflds, so cnode was included */
835*fcf3ce44SJohn Forte 			addcnode = 0;
836*fcf3ce44SJohn Forte 		}
837*fcf3ce44SJohn Forte 
838*fcf3ce44SJohn Forte 		bufp = buf;
839*fcf3ce44SJohn Forte 		if (addcnode) {
840*fcf3ce44SJohn Forte 			cfg_insert_node(cfg, &chead[0], buf, section);
841*fcf3ce44SJohn Forte 		}
842*fcf3ce44SJohn Forte 
843*fcf3ce44SJohn Forte 		(*cfp->cf_pp->replacecf)
844*fcf3ce44SJohn Forte 			(cfp, bufp, table_index, relnum - secnum);
845*fcf3ce44SJohn Forte 
846*fcf3ce44SJohn Forte 		return (TRUE);
847*fcf3ce44SJohn Forte 	}
848*fcf3ce44SJohn Forte 
849*fcf3ce44SJohn Forte 	/*
850*fcf3ce44SJohn Forte 	 * Both Set and field are specified
851*fcf3ce44SJohn Forte 	 * needs to get current whole entry and old requested field
852*fcf3ce44SJohn Forte 	 * copy good fields to buf, replace new field in buf
853*fcf3ce44SJohn Forte 	 * move everything depending of new size
854*fcf3ce44SJohn Forte 	 * replace entry so set# does not change
855*fcf3ce44SJohn Forte 	 */
856*fcf3ce44SJohn Forte 	if (setp && itemp) {
857*fcf3ce44SJohn Forte 		int rc;
858*fcf3ce44SJohn Forte 		int nflds;
859*fcf3ce44SJohn Forte 		int cnodepos;
860*fcf3ce44SJohn Forte 
861*fcf3ce44SJohn Forte 		for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
862*fcf3ce44SJohn Forte 			if (!cfp->cf_fd) continue;
863*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
864*fcf3ce44SJohn Forte 				if (!cfg_read(cfp)) {
865*fcf3ce44SJohn Forte 					cfg_perror_str =
866*fcf3ce44SJohn Forte 						dgettext("cfg", CFG_RDFAILED);
867*fcf3ce44SJohn Forte 					cfg_severity = CFG_EFATAL;
868*fcf3ce44SJohn Forte 					return (-1);
869*fcf3ce44SJohn Forte 				}
870*fcf3ce44SJohn Forte 			}
871*fcf3ce44SJohn Forte 			while (numfound < setnum) {
872*fcf3ce44SJohn Forte 				if ((*cfp->cf_pp->readcf)
873*fcf3ce44SJohn Forte 				    (cfp, buf, table_offset, relnum - secnum)
874*fcf3ce44SJohn Forte 				    == NULL) {
875*fcf3ce44SJohn Forte 					secnum = relnum - 1;
876*fcf3ce44SJohn Forte 					break;
877*fcf3ce44SJohn Forte 				}
878*fcf3ce44SJohn Forte 				if (cfg_filter_node(cfg, &chead[0], buf,
879*fcf3ce44SJohn Forte 					section))
880*fcf3ce44SJohn Forte 					numfound++;
881*fcf3ce44SJohn Forte 
882*fcf3ce44SJohn Forte 				if (numfound == setnum)
883*fcf3ce44SJohn Forte 					break;
884*fcf3ce44SJohn Forte 
885*fcf3ce44SJohn Forte 				relnum++;
886*fcf3ce44SJohn Forte 			}
887*fcf3ce44SJohn Forte 			if (numfound == setnum)
888*fcf3ce44SJohn Forte 				break;
889*fcf3ce44SJohn Forte 		}
890*fcf3ce44SJohn Forte 
891*fcf3ce44SJohn Forte 		/* Fail to find anything? */
892*fcf3ce44SJohn Forte 		if (cfp >= &cfg->cf[2]) {
893*fcf3ce44SJohn Forte 			errno = ESRCH;
894*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", strerror(errno));
895*fcf3ce44SJohn Forte 			cfg_severity = CFG_ENONFATAL;
896*fcf3ce44SJohn Forte 			return (-1);
897*fcf3ce44SJohn Forte 		}
898*fcf3ce44SJohn Forte 
899*fcf3ce44SJohn Forte 		nflds = cfg_get_num_flds(&chead[0], section, &table_index);
900*fcf3ce44SJohn Forte 		fldnum = cfg_get_item(&chead[0], section, itemp);
901*fcf3ce44SJohn Forte 		bzero(newbuf, sizeof (newbuf));
902*fcf3ce44SJohn Forte 		strncpy(newbuf, " ", 1);
903*fcf3ce44SJohn Forte 
904*fcf3ce44SJohn Forte 		/* move good flds in */
905*fcf3ce44SJohn Forte 		rc = cfg_fld_mov(newbuf, buf, 1, fldnum - 1);
906*fcf3ce44SJohn Forte 		if (rc < 0)
907*fcf3ce44SJohn Forte 			return (rc);
908*fcf3ce44SJohn Forte 
909*fcf3ce44SJohn Forte 		/* move new fld in */
910*fcf3ce44SJohn Forte 		strncat(newbuf, value, strlen(value));
911*fcf3ce44SJohn Forte 		strcat(newbuf, " ");
912*fcf3ce44SJohn Forte 
913*fcf3ce44SJohn Forte 		/* move remaining flds in */
914*fcf3ce44SJohn Forte 		rc = cfg_fld_mov(newbuf, buf, fldnum + 1, nflds);
915*fcf3ce44SJohn Forte 		if (rc < 0)
916*fcf3ce44SJohn Forte 			return (rc);
917*fcf3ce44SJohn Forte 
918*fcf3ce44SJohn Forte 		cnodepos = cfg_get_item(&chead[0], section, "cnode");
919*fcf3ce44SJohn Forte 		if ((cnodepos >= 0) && strcmp(itemp, "cnode") != 0) {
920*fcf3ce44SJohn Forte 			/* add cnode if user didn't specify it */
921*fcf3ce44SJohn Forte 			cfg_insert_node(cfg, &chead[0],
922*fcf3ce44SJohn Forte 			    newbuf, section);
923*fcf3ce44SJohn Forte 		}
924*fcf3ce44SJohn Forte 
925*fcf3ce44SJohn Forte 		(*cfp->cf_pp->replacecf)
926*fcf3ce44SJohn Forte 			(cfp, newbuf, table_index, relnum - secnum);
927*fcf3ce44SJohn Forte 
928*fcf3ce44SJohn Forte 		return (TRUE);
929*fcf3ce44SJohn Forte 	}
930*fcf3ce44SJohn Forte 
931*fcf3ce44SJohn Forte 	if (noset) {	/* blast entire thing in */
932*fcf3ce44SJohn Forte 		int nflds;
933*fcf3ce44SJohn Forte 		int got;
934*fcf3ce44SJohn Forte 		int cnodepos;
935*fcf3ce44SJohn Forte 
936*fcf3ce44SJohn Forte 		bufp = buf;
937*fcf3ce44SJohn Forte 		if (!value) { /* we shouldn't be here */
938*fcf3ce44SJohn Forte 			errno = EINVAL;
939*fcf3ce44SJohn Forte 			return (-1);
940*fcf3ce44SJohn Forte 		}
941*fcf3ce44SJohn Forte 		strncat(buf, " ", 1);
942*fcf3ce44SJohn Forte 		if (strlen(value) > sizeof (buf) - 2) {
943*fcf3ce44SJohn Forte 			errno = E2BIG;
944*fcf3ce44SJohn Forte 			return (-1);
945*fcf3ce44SJohn Forte 		}
946*fcf3ce44SJohn Forte 
947*fcf3ce44SJohn Forte 		strncat(buf, value, val_len);
948*fcf3ce44SJohn Forte 		nflds = cfg_get_num_flds(&chead[0], section, &table_index);
949*fcf3ce44SJohn Forte 		got = cfg_cnt_flds(value);
950*fcf3ce44SJohn Forte 
951*fcf3ce44SJohn Forte 		cnodepos = cfg_get_item(&chead[0], section, "cnode");
952*fcf3ce44SJohn Forte 		if (cnodepos < 0 || got >= cnodepos) {
953*fcf3ce44SJohn Forte 			/* no cnode, or cnode was specified by caller */
954*fcf3ce44SJohn Forte 			addcnode = 0;
955*fcf3ce44SJohn Forte 		}
956*fcf3ce44SJohn Forte 
957*fcf3ce44SJohn Forte 		if (got < nflds) {
958*fcf3ce44SJohn Forte 			for (/* CSTYLED */; got < nflds; got++)
959*fcf3ce44SJohn Forte 				strncat(buf, " - ", 3);
960*fcf3ce44SJohn Forte 		} else if (got > nflds) {
961*fcf3ce44SJohn Forte 			errno = EINVAL; /* specified too many fields */
962*fcf3ce44SJohn Forte 			return (-1);
963*fcf3ce44SJohn Forte 		} else {
964*fcf3ce44SJohn Forte 			/* got == nflds, so cnode was included */
965*fcf3ce44SJohn Forte 			addcnode = 0;
966*fcf3ce44SJohn Forte 		}
967*fcf3ce44SJohn Forte 
968*fcf3ce44SJohn Forte 		if (addcnode) {
969*fcf3ce44SJohn Forte 			cfg_insert_node(cfg, &chead[0], buf, section);
970*fcf3ce44SJohn Forte 		}
971*fcf3ce44SJohn Forte 
972*fcf3ce44SJohn Forte 		/* Make sure we put this entry in the right database */
973*fcf3ce44SJohn Forte 		if (cfg_is_cnode(cfg, &chead[0], buf, section) &&
974*fcf3ce44SJohn Forte 		    cfg->cf[1].cf_fd)
975*fcf3ce44SJohn Forte 			cfp = &cfg->cf[1];
976*fcf3ce44SJohn Forte 		else
977*fcf3ce44SJohn Forte 			cfp = &cfg->cf[0];
978*fcf3ce44SJohn Forte 
979*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
980*fcf3ce44SJohn Forte 			if (!cfg_read(cfp)) {
981*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
982*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
983*fcf3ce44SJohn Forte 				return (-1);
984*fcf3ce44SJohn Forte 			}
985*fcf3ce44SJohn Forte 		}
986*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_csize + strlen(buf) > CFG_DEFAULT_SSIZE) {
987*fcf3ce44SJohn Forte 			errno = ENOSPC;
988*fcf3ce44SJohn Forte 			return (-1);
989*fcf3ce44SJohn Forte 		}
990*fcf3ce44SJohn Forte 
991*fcf3ce44SJohn Forte 		(*cfp->cf_pp->addcf)(cfp, bufp, table_index);
992*fcf3ce44SJohn Forte 
993*fcf3ce44SJohn Forte 		return (TRUE);
994*fcf3ce44SJohn Forte 	}
995*fcf3ce44SJohn Forte 
996*fcf3ce44SJohn Forte 	errno = EINVAL;
997*fcf3ce44SJohn Forte 	cfg_perror_str = strerror(errno);
998*fcf3ce44SJohn Forte 	cfg_severity = CFG_ENONFATAL;
999*fcf3ce44SJohn Forte 	return (-1);
1000*fcf3ce44SJohn Forte }
1001*fcf3ce44SJohn Forte 
1002*fcf3ce44SJohn Forte /*
1003*fcf3ce44SJohn Forte  * cfg_encode_char
1004*fcf3ce44SJohn Forte  *
1005*fcf3ce44SJohn Forte  *	Encode a single character into % + hex ascii value
1006*fcf3ce44SJohn Forte  */
1007*fcf3ce44SJohn Forte static void
1008*fcf3ce44SJohn Forte cfg_encode_char(char *result, char ch)
1009*fcf3ce44SJohn Forte {
1010*fcf3ce44SJohn Forte 	*result++ = '%';
1011*fcf3ce44SJohn Forte 	*result++ = dectohex[ (ch >> 4) & 0xf ];
1012*fcf3ce44SJohn Forte 	*result++ = dectohex[ ch & 0xf ];
1013*fcf3ce44SJohn Forte }
1014*fcf3ce44SJohn Forte 
1015*fcf3ce44SJohn Forte /*
1016*fcf3ce44SJohn Forte  * cfg_decode_char
1017*fcf3ce44SJohn Forte  *
1018*fcf3ce44SJohn Forte  *	Reverses cfg_encode_char
1019*fcf3ce44SJohn Forte  */
1020*fcf3ce44SJohn Forte static char
1021*fcf3ce44SJohn Forte cfg_decode_char(char *code)
1022*fcf3ce44SJohn Forte {
1023*fcf3ce44SJohn Forte 	char retval;
1024*fcf3ce44SJohn Forte 	if (*code != '%') {
1025*fcf3ce44SJohn Forte 		return ('\0');
1026*fcf3ce44SJohn Forte 	}
1027*fcf3ce44SJohn Forte 	++code;
1028*fcf3ce44SJohn Forte 	if (!isxdigit(*code))
1029*fcf3ce44SJohn Forte 		return ('\0');
1030*fcf3ce44SJohn Forte 	retval = (isdigit(*code)? *code - '0' : *code - 'a' + 10);
1031*fcf3ce44SJohn Forte 	retval <<= 4;
1032*fcf3ce44SJohn Forte 	++code;
1033*fcf3ce44SJohn Forte 	if (!isxdigit(*code))
1034*fcf3ce44SJohn Forte 		return ('\0');
1035*fcf3ce44SJohn Forte 	retval |= (isdigit(*code)? *code - '0' : *code - 'a' + 10);
1036*fcf3ce44SJohn Forte 
1037*fcf3ce44SJohn Forte 	return (retval);
1038*fcf3ce44SJohn Forte }
1039*fcf3ce44SJohn Forte 
1040*fcf3ce44SJohn Forte /*
1041*fcf3ce44SJohn Forte  * cfg_encode_option
1042*fcf3ce44SJohn Forte  *
1043*fcf3ce44SJohn Forte  *	Transforms the key and value strings so that special characters
1044*fcf3ce44SJohn Forte  *	can be used within the options field.
1045*fcf3ce44SJohn Forte  *
1046*fcf3ce44SJohn Forte  * Returns:
1047*fcf3ce44SJohn Forte  *	Length of encoded string; -1 on failure
1048*fcf3ce44SJohn Forte  */
1049*fcf3ce44SJohn Forte static int
1050*fcf3ce44SJohn Forte cfg_encode_string(char *str, char *output, int outlen)
1051*fcf3ce44SJohn Forte {
1052*fcf3ce44SJohn Forte 	char *mem, *p, *q;
1053*fcf3ce44SJohn Forte 	int curlen;
1054*fcf3ce44SJohn Forte 
1055*fcf3ce44SJohn Forte 
1056*fcf3ce44SJohn Forte 	/* first, scan through the tag string converting %-signs */
1057*fcf3ce44SJohn Forte 	p = str;
1058*fcf3ce44SJohn Forte 	q = output;
1059*fcf3ce44SJohn Forte 	curlen = 0;
1060*fcf3ce44SJohn Forte 	while (*p && curlen < outlen) {
1061*fcf3ce44SJohn Forte 		if (*p == '%') {
1062*fcf3ce44SJohn Forte 			if (curlen + 3 >= outlen) {
1063*fcf3ce44SJohn Forte 				return (-1);
1064*fcf3ce44SJohn Forte 			}
1065*fcf3ce44SJohn Forte 			cfg_encode_char(q, *p);
1066*fcf3ce44SJohn Forte 			curlen += 3;
1067*fcf3ce44SJohn Forte 			q += 3;
1068*fcf3ce44SJohn Forte 		} else {
1069*fcf3ce44SJohn Forte 			*q++ = *p;
1070*fcf3ce44SJohn Forte 			++curlen;
1071*fcf3ce44SJohn Forte 		}
1072*fcf3ce44SJohn Forte 		++p;
1073*fcf3ce44SJohn Forte 	}
1074*fcf3ce44SJohn Forte 	if (curlen < outlen)
1075*fcf3ce44SJohn Forte 		*q = '\0';
1076*fcf3ce44SJohn Forte 
1077*fcf3ce44SJohn Forte 	/* now encode special characters */
1078*fcf3ce44SJohn Forte 	p = mem = strdup(output);
1079*fcf3ce44SJohn Forte 	q = output;
1080*fcf3ce44SJohn Forte 	curlen = 0;
1081*fcf3ce44SJohn Forte 	while (*p && curlen < outlen) {
1082*fcf3ce44SJohn Forte 		if (strchr(CHARS_TO_ENCODE, *p) != 0) {
1083*fcf3ce44SJohn Forte 			if (curlen + 3 >= outlen) {
1084*fcf3ce44SJohn Forte 				free(mem);
1085*fcf3ce44SJohn Forte 				return (-1);
1086*fcf3ce44SJohn Forte 			}
1087*fcf3ce44SJohn Forte 			cfg_encode_char(q, *p);
1088*fcf3ce44SJohn Forte 			curlen += 3;
1089*fcf3ce44SJohn Forte 			q += 3;
1090*fcf3ce44SJohn Forte 		} else {
1091*fcf3ce44SJohn Forte 			*q++ = *p;
1092*fcf3ce44SJohn Forte 			++curlen;
1093*fcf3ce44SJohn Forte 		}
1094*fcf3ce44SJohn Forte 		++p;
1095*fcf3ce44SJohn Forte 	}
1096*fcf3ce44SJohn Forte 	free(mem);
1097*fcf3ce44SJohn Forte 
1098*fcf3ce44SJohn Forte 	if (curlen < outlen)
1099*fcf3ce44SJohn Forte 		*q = '\0';
1100*fcf3ce44SJohn Forte 	/* LINTED possible ptrdiff_t overflow */
1101*fcf3ce44SJohn Forte 	return (q - output);
1102*fcf3ce44SJohn Forte }
1103*fcf3ce44SJohn Forte 
1104*fcf3ce44SJohn Forte /*
1105*fcf3ce44SJohn Forte  * cfg_decode_option
1106*fcf3ce44SJohn Forte  *
1107*fcf3ce44SJohn Forte  *	Given a string, decodes any %-encodes on it.
1108*fcf3ce44SJohn Forte  */
1109*fcf3ce44SJohn Forte static void
1110*fcf3ce44SJohn Forte cfg_decode_string(char *str, char *output, int outlen)
1111*fcf3ce44SJohn Forte {
1112*fcf3ce44SJohn Forte 	char *p, *q;
1113*fcf3ce44SJohn Forte 	int curlen;
1114*fcf3ce44SJohn Forte 
1115*fcf3ce44SJohn Forte 	p = str;
1116*fcf3ce44SJohn Forte 	q = output;
1117*fcf3ce44SJohn Forte 	curlen = 0;
1118*fcf3ce44SJohn Forte 	while (*p && curlen < outlen) {
1119*fcf3ce44SJohn Forte 		if (*p == '%') {
1120*fcf3ce44SJohn Forte 			char ch = cfg_decode_char(p);
1121*fcf3ce44SJohn Forte 			if (!ch) {
1122*fcf3ce44SJohn Forte 				*q++ = *p++;
1123*fcf3ce44SJohn Forte 				++curlen;
1124*fcf3ce44SJohn Forte 			} else {
1125*fcf3ce44SJohn Forte 				*q++ = ch;
1126*fcf3ce44SJohn Forte 				p += 3;
1127*fcf3ce44SJohn Forte 				++curlen;
1128*fcf3ce44SJohn Forte 			}
1129*fcf3ce44SJohn Forte 		} else {
1130*fcf3ce44SJohn Forte 			*q++ = *p++;
1131*fcf3ce44SJohn Forte 			++curlen;
1132*fcf3ce44SJohn Forte 		}
1133*fcf3ce44SJohn Forte 	}
1134*fcf3ce44SJohn Forte 	if (curlen < outlen)
1135*fcf3ce44SJohn Forte 		*q = '\0';
1136*fcf3ce44SJohn Forte }
1137*fcf3ce44SJohn Forte 
1138*fcf3ce44SJohn Forte /*
1139*fcf3ce44SJohn Forte  * cfg_get_options
1140*fcf3ce44SJohn Forte  * return first options set from basekey
1141*fcf3ce44SJohn Forte  * Subsequent calls with basekey = NULL return next option if any
1142*fcf3ce44SJohn Forte  * into tag and val
1143*fcf3ce44SJohn Forte  * returns
1144*fcf3ce44SJohn Forte  *	true 	success and more options data
1145*fcf3ce44SJohn Forte  *	-1 	no options data
1146*fcf3ce44SJohn Forte  */
1147*fcf3ce44SJohn Forte 
1148*fcf3ce44SJohn Forte int
1149*fcf3ce44SJohn Forte cfg_get_options(CFGFILE *cfg, int section, const char *basekey, char *tag,
1150*fcf3ce44SJohn Forte     int tag_len, char *val, int val_len)
1151*fcf3ce44SJohn Forte {
1152*fcf3ce44SJohn Forte 	static char buf[CFG_MAX_BUF];
1153*fcf3ce44SJohn Forte 	char decode_buf[CFG_MAX_BUF];
1154*fcf3ce44SJohn Forte 	int rc;
1155*fcf3ce44SJohn Forte 	char *ttag, *tval;
1156*fcf3ce44SJohn Forte 
1157*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1158*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1159*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1160*fcf3ce44SJohn Forte 		return (-1);
1161*fcf3ce44SJohn Forte 	}
1162*fcf3ce44SJohn Forte 
1163*fcf3ce44SJohn Forte 	errno = ENOSYS;
1164*fcf3ce44SJohn Forte 	if (basekey == 0) {
1165*fcf3ce44SJohn Forte 		ttag = strtok(NULL, "=");
1166*fcf3ce44SJohn Forte 	} else {
1167*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
1168*fcf3ce44SJohn Forte 		if (section == CFG_SEC_CONF) {
1169*fcf3ce44SJohn Forte 			rc = cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF);
1170*fcf3ce44SJohn Forte 		} else
1171*fcf3ce44SJohn Forte 			return (-1);
1172*fcf3ce44SJohn Forte 		if (rc < 0)
1173*fcf3ce44SJohn Forte 			return (rc);
1174*fcf3ce44SJohn Forte 		/* buf now contains raw options data */
1175*fcf3ce44SJohn Forte 		ttag = strtok(buf, "=");
1176*fcf3ce44SJohn Forte 	}
1177*fcf3ce44SJohn Forte 	tval = strtok(NULL, ";");
1178*fcf3ce44SJohn Forte 	if (!(tval) || !(ttag))
1179*fcf3ce44SJohn Forte 		return (-1);
1180*fcf3ce44SJohn Forte 	if ((strlen(tval) > val_len) || (strlen(ttag) > tag_len)) {
1181*fcf3ce44SJohn Forte 		errno = E2BIG;
1182*fcf3ce44SJohn Forte 		return (-1);
1183*fcf3ce44SJohn Forte 	}
1184*fcf3ce44SJohn Forte 	cfg_decode_string(tval, decode_buf, CFG_MAX_BUF);
1185*fcf3ce44SJohn Forte 	strncpy(val, decode_buf, val_len);
1186*fcf3ce44SJohn Forte 	cfg_decode_string(ttag, decode_buf, CFG_MAX_BUF);
1187*fcf3ce44SJohn Forte 	strncpy(tag, decode_buf, tag_len);
1188*fcf3ce44SJohn Forte 	errno = 0;
1189*fcf3ce44SJohn Forte 	return (TRUE);
1190*fcf3ce44SJohn Forte }
1191*fcf3ce44SJohn Forte 
1192*fcf3ce44SJohn Forte /*
1193*fcf3ce44SJohn Forte  * cfg_put_options
1194*fcf3ce44SJohn Forte  *
1195*fcf3ce44SJohn Forte  *	Replaces existing tag with new val.  If tag doesn't exist,
1196*fcf3ce44SJohn Forte  *	then it adds a new tag with the specified val.
1197*fcf3ce44SJohn Forte  *
1198*fcf3ce44SJohn Forte  * Return:
1199*fcf3ce44SJohn Forte  *	true	success
1200*fcf3ce44SJohn Forte  *	-1	incorrect section, or read error from cfg DB
1201*fcf3ce44SJohn Forte  */
1202*fcf3ce44SJohn Forte int
1203*fcf3ce44SJohn Forte cfg_put_options(CFGFILE *cfg, int section, const char *basekey, char *tag,
1204*fcf3ce44SJohn Forte     char *val)
1205*fcf3ce44SJohn Forte {
1206*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1207*fcf3ce44SJohn Forte 	char encode_buf[CFG_MAX_BUF];
1208*fcf3ce44SJohn Forte 	char *p;
1209*fcf3ce44SJohn Forte 	int enclen;
1210*fcf3ce44SJohn Forte 
1211*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1212*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1213*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1214*fcf3ce44SJohn Forte 		return (-1);
1215*fcf3ce44SJohn Forte 	}
1216*fcf3ce44SJohn Forte 
1217*fcf3ce44SJohn Forte 	errno = ENOSYS;
1218*fcf3ce44SJohn Forte 	bzero(buf, CFG_MAX_BUF);
1219*fcf3ce44SJohn Forte 	if (section != CFG_SEC_CONF) {
1220*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1221*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1222*fcf3ce44SJohn Forte 		return (-1);
1223*fcf3ce44SJohn Forte 	}
1224*fcf3ce44SJohn Forte 	if (!tag || !*tag || !val || !*val)
1225*fcf3ce44SJohn Forte 		return (-1);
1226*fcf3ce44SJohn Forte 	if (cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
1227*fcf3ce44SJohn Forte 		/* cfg severity & perror_str set up cfg_get_cstring() */
1228*fcf3ce44SJohn Forte 		return (-1);
1229*fcf3ce44SJohn Forte 	}
1230*fcf3ce44SJohn Forte 	*encode_buf = ';';
1231*fcf3ce44SJohn Forte 	enclen = cfg_encode_string(tag, &encode_buf[1], CFG_MAX_BUF - 1) + 1;
1232*fcf3ce44SJohn Forte 	if (enclen < 1 || (enclen + 1) >= CFG_MAX_BUF) {
1233*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1234*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "Buffer too small");
1235*fcf3ce44SJohn Forte 		return (-1);
1236*fcf3ce44SJohn Forte 	}
1237*fcf3ce44SJohn Forte 	encode_buf[enclen] = '=';
1238*fcf3ce44SJohn Forte 	encode_buf[enclen + 1] = '\0';
1239*fcf3ce44SJohn Forte 
1240*fcf3ce44SJohn Forte 	/* check the start of the string */
1241*fcf3ce44SJohn Forte 	if (strncmp(buf, &encode_buf[1], enclen) == 0) {
1242*fcf3ce44SJohn Forte 		/* locate the end of this option */
1243*fcf3ce44SJohn Forte 		p = strchr(buf, ';');
1244*fcf3ce44SJohn Forte 		if (p && *(p + 1) != '\0') {
1245*fcf3ce44SJohn Forte 			/* add the new tag to the end */
1246*fcf3ce44SJohn Forte 			++p;
1247*fcf3ce44SJohn Forte 			strcat(p, &encode_buf[1]);
1248*fcf3ce44SJohn Forte 		} else {
1249*fcf3ce44SJohn Forte 			/* completely overwrite the existing tag */
1250*fcf3ce44SJohn Forte 			p = buf;
1251*fcf3ce44SJohn Forte 			strcpy(p, &encode_buf[1]);
1252*fcf3ce44SJohn Forte 		}
1253*fcf3ce44SJohn Forte 		if (cfg_encode_string(val, encode_buf, CFG_MAX_BUF) < 0) {
1254*fcf3ce44SJohn Forte 			cfg_severity = CFG_ENONFATAL;
1255*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", "Buffer too small");
1256*fcf3ce44SJohn Forte 			return (-1);
1257*fcf3ce44SJohn Forte 		}
1258*fcf3ce44SJohn Forte 		strcat(p, encode_buf);
1259*fcf3ce44SJohn Forte 		strcat(p, ";");
1260*fcf3ce44SJohn Forte 		if (cfg_put_cstring(cfg, basekey, p, strlen(p)) < 0) {
1261*fcf3ce44SJohn Forte 			/* severity & perror_str set by cfg_put_cstring */
1262*fcf3ce44SJohn Forte 			return (-1);
1263*fcf3ce44SJohn Forte 		}
1264*fcf3ce44SJohn Forte 		errno = 0;
1265*fcf3ce44SJohn Forte 		return (TRUE);
1266*fcf3ce44SJohn Forte 	}
1267*fcf3ce44SJohn Forte 
1268*fcf3ce44SJohn Forte 	/* it's hiding somewhere inside... */
1269*fcf3ce44SJohn Forte 	p = strstr(buf, encode_buf);
1270*fcf3ce44SJohn Forte 	if (p) {
1271*fcf3ce44SJohn Forte 		/* delete the old value */
1272*fcf3ce44SJohn Forte 		char *q = strchr(p + 1, ';');
1273*fcf3ce44SJohn Forte 		if (q) {
1274*fcf3ce44SJohn Forte 			strcpy(p + 1, q + 1);
1275*fcf3ce44SJohn Forte 		} else {
1276*fcf3ce44SJohn Forte 			*p = '\0';
1277*fcf3ce44SJohn Forte 		}
1278*fcf3ce44SJohn Forte 		strcat(buf, &encode_buf[1]);
1279*fcf3ce44SJohn Forte 	} else if (*buf) {
1280*fcf3ce44SJohn Forte 		strcat(buf, &encode_buf[1]);
1281*fcf3ce44SJohn Forte 	} else {
1282*fcf3ce44SJohn Forte 		strcpy(buf, &encode_buf[1]);
1283*fcf3ce44SJohn Forte 	}
1284*fcf3ce44SJohn Forte 	enclen = cfg_encode_string(val, encode_buf, CFG_MAX_BUF);
1285*fcf3ce44SJohn Forte 	if (enclen < 0 || (strlen(buf) + enclen) >= CFG_MAX_BUF) {
1286*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1287*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "Buffer too small");
1288*fcf3ce44SJohn Forte 		return (-1);
1289*fcf3ce44SJohn Forte 	}
1290*fcf3ce44SJohn Forte 	strcat(buf, encode_buf);
1291*fcf3ce44SJohn Forte 	strcat(buf, ";");
1292*fcf3ce44SJohn Forte 	if (cfg_put_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
1293*fcf3ce44SJohn Forte 		/* severity & perror_str set by cfg_put_cstring */
1294*fcf3ce44SJohn Forte 		return (-1);
1295*fcf3ce44SJohn Forte 	}
1296*fcf3ce44SJohn Forte 	errno = 0;
1297*fcf3ce44SJohn Forte 	return (TRUE);
1298*fcf3ce44SJohn Forte }
1299*fcf3ce44SJohn Forte 
1300*fcf3ce44SJohn Forte /*
1301*fcf3ce44SJohn Forte  * cfg_get_single_option
1302*fcf3ce44SJohn Forte  *
1303*fcf3ce44SJohn Forte  *	Scans the options string for the specified option and returns
1304*fcf3ce44SJohn Forte  *	the decoded value
1305*fcf3ce44SJohn Forte  *
1306*fcf3ce44SJohn Forte  * Return:
1307*fcf3ce44SJohn Forte  *	true	success
1308*fcf3ce44SJohn Forte  *	-1	incorrect section, or read error from cfg DB
1309*fcf3ce44SJohn Forte  */
1310*fcf3ce44SJohn Forte int
1311*fcf3ce44SJohn Forte cfg_get_single_option(CFGFILE *cfg, int section, const char *basekey, char *tag,
1312*fcf3ce44SJohn Forte     char *val, int val_len)
1313*fcf3ce44SJohn Forte {
1314*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1315*fcf3ce44SJohn Forte 	char encode_buf[CFG_MAX_BUF];
1316*fcf3ce44SJohn Forte 	char *p, *q;
1317*fcf3ce44SJohn Forte 	int enclen;
1318*fcf3ce44SJohn Forte 
1319*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1320*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1321*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1322*fcf3ce44SJohn Forte 		return (-1);
1323*fcf3ce44SJohn Forte 	}
1324*fcf3ce44SJohn Forte 
1325*fcf3ce44SJohn Forte 	errno = ENOSYS;
1326*fcf3ce44SJohn Forte 	bzero(buf, CFG_MAX_BUF);
1327*fcf3ce44SJohn Forte 	if (section != CFG_SEC_CONF) {
1328*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1329*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1330*fcf3ce44SJohn Forte 		return (-1);
1331*fcf3ce44SJohn Forte 	}
1332*fcf3ce44SJohn Forte 	if (cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
1333*fcf3ce44SJohn Forte 		/* severity & perror_str set by cfg_get_cstring */
1334*fcf3ce44SJohn Forte 		return (-1);
1335*fcf3ce44SJohn Forte 	}
1336*fcf3ce44SJohn Forte 
1337*fcf3ce44SJohn Forte 	*encode_buf = ';';
1338*fcf3ce44SJohn Forte 	enclen = cfg_encode_string(tag, &encode_buf[1], CFG_MAX_BUF - 1) + 1;
1339*fcf3ce44SJohn Forte 	if (enclen < 1 || (enclen + 1) >= CFG_MAX_BUF) {
1340*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1341*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "Buffer too small");
1342*fcf3ce44SJohn Forte 		return (-1);
1343*fcf3ce44SJohn Forte 	}
1344*fcf3ce44SJohn Forte 	encode_buf[enclen] = '=';
1345*fcf3ce44SJohn Forte 	encode_buf[enclen + 1] = '\0';
1346*fcf3ce44SJohn Forte 
1347*fcf3ce44SJohn Forte 	/* check the start of the string */
1348*fcf3ce44SJohn Forte 	if (strncmp(buf, &encode_buf[1], enclen) == 0) {
1349*fcf3ce44SJohn Forte 		p = strchr(buf, '=');
1350*fcf3ce44SJohn Forte 		if (!p) {
1351*fcf3ce44SJohn Forte 			cfg_severity = CFG_ENONFATAL;
1352*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", "Option not found");
1353*fcf3ce44SJohn Forte 			return (-1);
1354*fcf3ce44SJohn Forte 		}
1355*fcf3ce44SJohn Forte 		++p;
1356*fcf3ce44SJohn Forte 		q = strchr(p, ';');
1357*fcf3ce44SJohn Forte 		if (q) {
1358*fcf3ce44SJohn Forte 			*q = '\0';
1359*fcf3ce44SJohn Forte 		}
1360*fcf3ce44SJohn Forte 		cfg_decode_string(p, val, val_len);
1361*fcf3ce44SJohn Forte 		errno = 0;
1362*fcf3ce44SJohn Forte 		return (TRUE);
1363*fcf3ce44SJohn Forte 	}
1364*fcf3ce44SJohn Forte 
1365*fcf3ce44SJohn Forte 	/* it's hiding somewhere inside... */
1366*fcf3ce44SJohn Forte 	p = strstr(buf, encode_buf);
1367*fcf3ce44SJohn Forte 	if (p) {
1368*fcf3ce44SJohn Forte 		p += enclen + 1;
1369*fcf3ce44SJohn Forte 		q = strchr(p, ';');
1370*fcf3ce44SJohn Forte 		if (q) {
1371*fcf3ce44SJohn Forte 			*q = '\0';
1372*fcf3ce44SJohn Forte 		}
1373*fcf3ce44SJohn Forte 		cfg_decode_string(p, val, val_len);
1374*fcf3ce44SJohn Forte 		errno = 0;
1375*fcf3ce44SJohn Forte 		return (TRUE);
1376*fcf3ce44SJohn Forte 	}
1377*fcf3ce44SJohn Forte 
1378*fcf3ce44SJohn Forte 	/* key not found */
1379*fcf3ce44SJohn Forte 	return (-1);
1380*fcf3ce44SJohn Forte 
1381*fcf3ce44SJohn Forte }
1382*fcf3ce44SJohn Forte 
1383*fcf3ce44SJohn Forte /*
1384*fcf3ce44SJohn Forte  * cfg_del_option
1385*fcf3ce44SJohn Forte  *
1386*fcf3ce44SJohn Forte  *	Removes a single key=val pair from the specified option field
1387*fcf3ce44SJohn Forte  *
1388*fcf3ce44SJohn Forte  * Return:
1389*fcf3ce44SJohn Forte  *	true	success
1390*fcf3ce44SJohn Forte  *	-1	unable to update config
1391*fcf3ce44SJohn Forte  */
1392*fcf3ce44SJohn Forte int
1393*fcf3ce44SJohn Forte cfg_del_option(CFGFILE *cfg, int section, const char *basekey, char *tag)
1394*fcf3ce44SJohn Forte {
1395*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
1396*fcf3ce44SJohn Forte 	char encode_buf[CFG_MAX_BUF];
1397*fcf3ce44SJohn Forte 	char *p, *q;
1398*fcf3ce44SJohn Forte 	int enclen, rc;
1399*fcf3ce44SJohn Forte 
1400*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1401*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1402*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1403*fcf3ce44SJohn Forte 		return (-1);
1404*fcf3ce44SJohn Forte 	}
1405*fcf3ce44SJohn Forte 
1406*fcf3ce44SJohn Forte 	bzero(buf, CFG_MAX_BUF);
1407*fcf3ce44SJohn Forte 	if (section != CFG_SEC_CONF) {
1408*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1409*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1410*fcf3ce44SJohn Forte 		return (-1);
1411*fcf3ce44SJohn Forte 	}
1412*fcf3ce44SJohn Forte 	if (cfg_get_cstring(cfg, basekey, buf, CFG_MAX_BUF) < 0) {
1413*fcf3ce44SJohn Forte 		/* severity & perror_str are set by cfg_get_cstring */
1414*fcf3ce44SJohn Forte 		return (-1);
1415*fcf3ce44SJohn Forte 	}
1416*fcf3ce44SJohn Forte 
1417*fcf3ce44SJohn Forte 	*encode_buf = ';';
1418*fcf3ce44SJohn Forte 	enclen = cfg_encode_string(tag, &encode_buf[1], CFG_MAX_BUF - 1) + 1;
1419*fcf3ce44SJohn Forte 	if (enclen < 1 || (enclen + 1) >= CFG_MAX_BUF) {
1420*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
1421*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "Buffer too small");
1422*fcf3ce44SJohn Forte 		return (-1);
1423*fcf3ce44SJohn Forte 	}
1424*fcf3ce44SJohn Forte 	encode_buf[enclen] = '=';
1425*fcf3ce44SJohn Forte 	encode_buf[enclen + 1] = '\0';
1426*fcf3ce44SJohn Forte 
1427*fcf3ce44SJohn Forte 	/* check the start of the string */
1428*fcf3ce44SJohn Forte 	if (strncmp(buf, &encode_buf[1], enclen) == 0) {
1429*fcf3ce44SJohn Forte 		p = strchr(buf, ';');
1430*fcf3ce44SJohn Forte 		if (p && (*(p + 1) != '\0')) {
1431*fcf3ce44SJohn Forte 		    rc = cfg_put_cstring(cfg, basekey, p + 1, strlen(p + 1));
1432*fcf3ce44SJohn Forte 		} else {
1433*fcf3ce44SJohn Forte 		    rc = cfg_put_cstring(cfg, basekey, "-", 1);
1434*fcf3ce44SJohn Forte 		}
1435*fcf3ce44SJohn Forte 		/* severity & perror_str are set by cfg_put_cstring */
1436*fcf3ce44SJohn Forte 		return (rc);
1437*fcf3ce44SJohn Forte 	}
1438*fcf3ce44SJohn Forte 
1439*fcf3ce44SJohn Forte 	/* sigh */
1440*fcf3ce44SJohn Forte 	p = strstr(buf, encode_buf);
1441*fcf3ce44SJohn Forte 	if (!p) {
1442*fcf3ce44SJohn Forte 		/* already removed */
1443*fcf3ce44SJohn Forte 		return (TRUE);
1444*fcf3ce44SJohn Forte 	}
1445*fcf3ce44SJohn Forte 	q = strchr(p + 1, ';');
1446*fcf3ce44SJohn Forte 
1447*fcf3ce44SJohn Forte 	/*
1448*fcf3ce44SJohn Forte 	 * Now the string looks like:
1449*fcf3ce44SJohn Forte 	 *	| first few options | *p | option to remove | *q | rest | '\0'
1450*fcf3ce44SJohn Forte 	 */
1451*fcf3ce44SJohn Forte 
1452*fcf3ce44SJohn Forte 	if (!q) {
1453*fcf3ce44SJohn Forte 		/* hum... */
1454*fcf3ce44SJohn Forte 		*p = '\0';
1455*fcf3ce44SJohn Forte 	} else {
1456*fcf3ce44SJohn Forte 		strcpy(p, q);
1457*fcf3ce44SJohn Forte 	}
1458*fcf3ce44SJohn Forte 
1459*fcf3ce44SJohn Forte 	return (cfg_put_cstring(cfg, basekey, buf, strlen(buf)));
1460*fcf3ce44SJohn Forte }
1461*fcf3ce44SJohn Forte 
1462*fcf3ce44SJohn Forte static void
1463*fcf3ce44SJohn Forte cfg_set_memorymap(cfp_t *cfp)
1464*fcf3ce44SJohn Forte {
1465*fcf3ce44SJohn Forte 	cfgheader_t *hd = cfp->cf_head;
1466*fcf3ce44SJohn Forte 
1467*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1468*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "callocing %d for initial reads\n", hd->h_csize);
1469*fcf3ce44SJohn Forte #endif
1470*fcf3ce44SJohn Forte 
1471*fcf3ce44SJohn Forte 	hd->h_ccopy1 = (char *)calloc(hd->h_csize, sizeof (char));
1472*fcf3ce44SJohn Forte 	hd->h_ccopy2 = (char *)calloc(hd->h_csize, sizeof (char));
1473*fcf3ce44SJohn Forte 	hd->h_sizes1 = (int *)calloc(CFG_DEFAULT_PSIZE, sizeof (int));
1474*fcf3ce44SJohn Forte 	hd->h_sizes2 = (int *)calloc(CFG_DEFAULT_PSIZE, sizeof (int));
1475*fcf3ce44SJohn Forte }
1476*fcf3ce44SJohn Forte 
1477*fcf3ce44SJohn Forte /*
1478*fcf3ce44SJohn Forte  * cfg_init_header
1479*fcf3ce44SJohn Forte  * fill in default header info
1480*fcf3ce44SJohn Forte  */
1481*fcf3ce44SJohn Forte static void
1482*fcf3ce44SJohn Forte cfg_init_header(cfp_t *cfp)
1483*fcf3ce44SJohn Forte {
1484*fcf3ce44SJohn Forte 	time_t tloc;
1485*fcf3ce44SJohn Forte 	cfgheader_t *hd = cfp->cf_head;
1486*fcf3ce44SJohn Forte 
1487*fcf3ce44SJohn Forte 	hd->h_magic = (int32_t)CFG_NEW_MAGIC;
1488*fcf3ce44SJohn Forte 	hd->h_stamp = time(&tloc);
1489*fcf3ce44SJohn Forte 	hd->h_lock = 0;
1490*fcf3ce44SJohn Forte 	/* parser config */
1491*fcf3ce44SJohn Forte 	hd->h_parsesize = 0;
1492*fcf3ce44SJohn Forte 	hd->h_parseoff = 0;
1493*fcf3ce44SJohn Forte 	hd->h_csize = 0;
1494*fcf3ce44SJohn Forte 	hd->h_psize = 0;
1495*fcf3ce44SJohn Forte 	hd->h_cfgs = NULL;
1496*fcf3ce44SJohn Forte 	hd->h_ncfgs = 0;
1497*fcf3ce44SJohn Forte 	hd->h_seq1 = hd->h_seq2 = 1;
1498*fcf3ce44SJohn Forte 	bzero(hd->h_cfgsizes, MAX_CFG * sizeof (int));
1499*fcf3ce44SJohn Forte }
1500*fcf3ce44SJohn Forte /*
1501*fcf3ce44SJohn Forte  * cfg_read
1502*fcf3ce44SJohn Forte  * read header and all sections of configuration file
1503*fcf3ce44SJohn Forte  * gets new data for incore copy
1504*fcf3ce44SJohn Forte  * removes invalid header state
1505*fcf3ce44SJohn Forte  * works even if config and persistent sections are empty
1506*fcf3ce44SJohn Forte  *
1507*fcf3ce44SJohn Forte  */
1508*fcf3ce44SJohn Forte static int
1509*fcf3ce44SJohn Forte cfg_read(cfp_t *cfp)
1510*fcf3ce44SJohn Forte {
1511*fcf3ce44SJohn Forte 	int rc;
1512*fcf3ce44SJohn Forte 	cfgheader_t *hd;
1513*fcf3ce44SJohn Forte 	int readsize = 0;
1514*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1515*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_read\n");
1516*fcf3ce44SJohn Forte #endif
1517*fcf3ce44SJohn Forte 
1518*fcf3ce44SJohn Forte 	if (!cfp->cf_head) {
1519*fcf3ce44SJohn Forte 		if ((hd = calloc(1, sizeof (*hd))) == NULL)
1520*fcf3ce44SJohn Forte 			return (FALSE);
1521*fcf3ce44SJohn Forte #ifdef DEBUG_HDR
1522*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "initial cfg header read\n");
1523*fcf3ce44SJohn Forte #endif
1524*fcf3ce44SJohn Forte 		cfp->cf_head = hd;
1525*fcf3ce44SJohn Forte 	}
1526*fcf3ce44SJohn Forte 
1527*fcf3ce44SJohn Forte 	if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
1528*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1529*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: seek header failed\n");
1530*fcf3ce44SJohn Forte #endif
1531*fcf3ce44SJohn Forte 		return (FALSE);
1532*fcf3ce44SJohn Forte 	}
1533*fcf3ce44SJohn Forte 
1534*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_head, 4);
1535*fcf3ce44SJohn Forte 	if (rc < 4) {
1536*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1537*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read magic number failed\n");
1538*fcf3ce44SJohn Forte #endif
1539*fcf3ce44SJohn Forte 		return (FALSE);
1540*fcf3ce44SJohn Forte 	}
1541*fcf3ce44SJohn Forte 
1542*fcf3ce44SJohn Forte 	if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
1543*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1544*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: seek header failed\n");
1545*fcf3ce44SJohn Forte #endif
1546*fcf3ce44SJohn Forte 		return (FALSE);
1547*fcf3ce44SJohn Forte 	}
1548*fcf3ce44SJohn Forte 
1549*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)(cfp, (char *)cfp->cf_head, sizeof (*hd));
1550*fcf3ce44SJohn Forte 	if (rc < sizeof (*hd)) {
1551*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1552*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read header failed\n");
1553*fcf3ce44SJohn Forte #endif
1554*fcf3ce44SJohn Forte 		return (FALSE);
1555*fcf3ce44SJohn Forte 	}
1556*fcf3ce44SJohn Forte 
1557*fcf3ce44SJohn Forte 	cfp->cf_head->h_cfgs = NULL;
1558*fcf3ce44SJohn Forte 	cfg_set_memorymap(cfp);
1559*fcf3ce44SJohn Forte 	if (cfp->cf_head->h_magic != CFG_NEW_MAGIC) {
1560*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1561*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg_read: wrong MAGIC number %x\n",
1562*fcf3ce44SJohn Forte 			cfp->cf_head->h_magic);
1563*fcf3ce44SJohn Forte #endif
1564*fcf3ce44SJohn Forte 		return (FALSE);
1565*fcf3ce44SJohn Forte 	}
1566*fcf3ce44SJohn Forte 
1567*fcf3ce44SJohn Forte 	cfp->cf_head->h_state &= ~(CFG_HDR_INVALID);
1568*fcf3ce44SJohn Forte 
1569*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1570*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "reading parser\n");
1571*fcf3ce44SJohn Forte #endif
1572*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)
1573*fcf3ce44SJohn Forte 		(cfp, (char *)cfp->cf_mapped, CFG_DEFAULT_PARSE_SIZE);
1574*fcf3ce44SJohn Forte 	if (rc < sizeof (*hd)) {
1575*fcf3ce44SJohn Forte #ifdef DEBUG
1576*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read parse config failed\n");
1577*fcf3ce44SJohn Forte #endif
1578*fcf3ce44SJohn Forte 		return (FALSE);
1579*fcf3ce44SJohn Forte 	}
1580*fcf3ce44SJohn Forte 
1581*fcf3ce44SJohn Forte 	readsize = cfp->cf_head->h_csize;
1582*fcf3ce44SJohn Forte 
1583*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1584*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "reading copy1 readsize = %d\n", readsize);
1585*fcf3ce44SJohn Forte #endif
1586*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)
1587*fcf3ce44SJohn Forte 		(cfp, (char *)cfp->cf_head->h_ccopy1, readsize);
1588*fcf3ce44SJohn Forte 	if (rc < 0) {
1589*fcf3ce44SJohn Forte 		/* don't fail just return */
1590*fcf3ce44SJohn Forte #ifdef DEBUG
1591*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read ccopy1 section failed\n");
1592*fcf3ce44SJohn Forte #endif
1593*fcf3ce44SJohn Forte 		return (FALSE);
1594*fcf3ce44SJohn Forte 	}
1595*fcf3ce44SJohn Forte 
1596*fcf3ce44SJohn Forte 	if ((*cfp->cf_pp->seek)
1597*fcf3ce44SJohn Forte 		(cfp, CFG_DEFAULT_SSIZE - rc, SEEK_CUR) < 0) {
1598*fcf3ce44SJohn Forte #ifdef DEBUG
1599*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: seek (SEEK_CUR) failed\n");
1600*fcf3ce44SJohn Forte #endif
1601*fcf3ce44SJohn Forte 		return (FALSE);
1602*fcf3ce44SJohn Forte 	}
1603*fcf3ce44SJohn Forte 
1604*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1605*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "reading copy2 readsize = %d\n", readsize);
1606*fcf3ce44SJohn Forte #endif
1607*fcf3ce44SJohn Forte 
1608*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)
1609*fcf3ce44SJohn Forte 		(cfp, (char *)cfp->cf_head->h_ccopy2, readsize);
1610*fcf3ce44SJohn Forte 	if (rc < 0) {
1611*fcf3ce44SJohn Forte 		/* don't fail just return */
1612*fcf3ce44SJohn Forte #ifdef DEBUG
1613*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read ccopy2 section failed\n");
1614*fcf3ce44SJohn Forte #endif
1615*fcf3ce44SJohn Forte 		return (FALSE);
1616*fcf3ce44SJohn Forte 	}
1617*fcf3ce44SJohn Forte 
1618*fcf3ce44SJohn Forte 	/* read the sizes of the lists from disk  */
1619*fcf3ce44SJohn Forte 	if ((*cfp->cf_pp->seek)
1620*fcf3ce44SJohn Forte 		(cfp, CFG_DEFAULT_SSIZE - rc, SEEK_CUR) < 0) {
1621*fcf3ce44SJohn Forte #ifdef DEBUG
1622*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: seek (SEEK_CUR) failed\n");
1623*fcf3ce44SJohn Forte #endif
1624*fcf3ce44SJohn Forte 		return (FALSE);
1625*fcf3ce44SJohn Forte 	}
1626*fcf3ce44SJohn Forte 
1627*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1628*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "reading sizes\n");
1629*fcf3ce44SJohn Forte #endif
1630*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)
1631*fcf3ce44SJohn Forte 		(cfp, (int *)cfp->cf_head->h_sizes1, CFG_DEFAULT_PSIZE);
1632*fcf3ce44SJohn Forte 	if (rc < 0) {
1633*fcf3ce44SJohn Forte #ifdef DEBUG
1634*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read h_sizes1 failed\n");
1635*fcf3ce44SJohn Forte #endif
1636*fcf3ce44SJohn Forte 		return (FALSE);
1637*fcf3ce44SJohn Forte 	}
1638*fcf3ce44SJohn Forte 
1639*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)
1640*fcf3ce44SJohn Forte 		(cfp, (int *)cfp->cf_head->h_sizes2, CFG_DEFAULT_PSIZE);
1641*fcf3ce44SJohn Forte 	if (rc < 0) {
1642*fcf3ce44SJohn Forte #ifdef DEBUG
1643*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: read h_sizes2 failed\n");
1644*fcf3ce44SJohn Forte #endif
1645*fcf3ce44SJohn Forte 		return (FALSE);
1646*fcf3ce44SJohn Forte 	}
1647*fcf3ce44SJohn Forte 
1648*fcf3ce44SJohn Forte 	/*
1649*fcf3ce44SJohn Forte 	 * If initial or invalid sequence, use first section
1650*fcf3ce44SJohn Forte 	 */
1651*fcf3ce44SJohn Forte 	if ((cfp->cf_head->h_seq1 <= 0) && (cfp->cf_head->h_seq2 <= 0)) {
1652*fcf3ce44SJohn Forte 		cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy1;
1653*fcf3ce44SJohn Forte 		cfp->cf_head->h_sizes = cfp->cf_head->h_sizes1;
1654*fcf3ce44SJohn Forte 	}
1655*fcf3ce44SJohn Forte 
1656*fcf3ce44SJohn Forte 	if (cfp->cf_head->h_seq1 >= cfp->cf_head->h_seq2) {
1657*fcf3ce44SJohn Forte 		cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy1;
1658*fcf3ce44SJohn Forte 		cfp->cf_head->h_sizes = cfp->cf_head->h_sizes1;
1659*fcf3ce44SJohn Forte 	} else {
1660*fcf3ce44SJohn Forte 		cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy2;
1661*fcf3ce44SJohn Forte 		cfp->cf_head->h_sizes = cfp->cf_head->h_sizes2;
1662*fcf3ce44SJohn Forte 	}
1663*fcf3ce44SJohn Forte 
1664*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1665*fcf3ce44SJohn Forte 	dump_status(cfp, "cfg_read");
1666*fcf3ce44SJohn Forte #endif
1667*fcf3ce44SJohn Forte 
1668*fcf3ce44SJohn Forte 	return (TRUE);
1669*fcf3ce44SJohn Forte }
1670*fcf3ce44SJohn Forte 
1671*fcf3ce44SJohn Forte /*
1672*fcf3ce44SJohn Forte  * cfg_lock
1673*fcf3ce44SJohn Forte  * Read-write locking of the configuration
1674*fcf3ce44SJohn Forte  * reads into core all sections
1675*fcf3ce44SJohn Forte  * builds parser trees for each section
1676*fcf3ce44SJohn Forte  * Returns: TRUE if the lock was acquired, FALSE otherwise.
1677*fcf3ce44SJohn Forte  */
1678*fcf3ce44SJohn Forte int
1679*fcf3ce44SJohn Forte cfg_lock(CFGFILE *cfg, CFGLOCK mode)
1680*fcf3ce44SJohn Forte {
1681*fcf3ce44SJohn Forte 	cfp_t *cfp;
1682*fcf3ce44SJohn Forte 	int is_locked = 0;
1683*fcf3ce44SJohn Forte 	int rc;
1684*fcf3ce44SJohn Forte 
1685*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1686*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1687*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1688*fcf3ce44SJohn Forte 		return (FALSE);
1689*fcf3ce44SJohn Forte 	}
1690*fcf3ce44SJohn Forte 
1691*fcf3ce44SJohn Forte 	if (mode == CFG_UPGRADE) {
1692*fcf3ce44SJohn Forte 		mode = CFG_WRLOCK;
1693*fcf3ce44SJohn Forte 	}
1694*fcf3ce44SJohn Forte 
1695*fcf3ce44SJohn Forte 	if (mode == CFG_WRLOCK && (cfg->cf[0].cf_flag & CFG_RDONLY)) {
1696*fcf3ce44SJohn Forte 		goto fail;
1697*fcf3ce44SJohn Forte 	}
1698*fcf3ce44SJohn Forte 
1699*fcf3ce44SJohn Forte 	/*
1700*fcf3ce44SJohn Forte 	 * if you don't even give me the right lock request,
1701*fcf3ce44SJohn Forte 	 * why should I give you one?
1702*fcf3ce44SJohn Forte 	 */
1703*fcf3ce44SJohn Forte 	if (mode != CFG_RDLOCK && mode != CFG_WRLOCK)
1704*fcf3ce44SJohn Forte 		goto fail;
1705*fcf3ce44SJohn Forte 
1706*fcf3ce44SJohn Forte 	if (cfg_lockd) {
1707*fcf3ce44SJohn Forte 		if (mode == CFG_WRLOCK)
1708*fcf3ce44SJohn Forte 			cfg_lockd_wrlock();
1709*fcf3ce44SJohn Forte 		else
1710*fcf3ce44SJohn Forte 			cfg_lockd_rdlock();
1711*fcf3ce44SJohn Forte 		is_locked = 1;
1712*fcf3ce44SJohn Forte 	} else {
1713*fcf3ce44SJohn Forte 
1714*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1715*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg_lock\n");
1716*fcf3ce44SJohn Forte #endif
1717*fcf3ce44SJohn Forte 		/* Lock is always based on local file pointer */
1718*fcf3ce44SJohn Forte 		cfg->cf[1].cf_lock = cfg->cf[0].cf_lock = cfg->cf[0].cf_fd;
1719*fcf3ce44SJohn Forte 
1720*fcf3ce44SJohn Forte 		if (!((cfg->cf[0].cf_flag & CFG_RDONLY) &&
1721*fcf3ce44SJohn Forte 			(mode == CFG_RDLOCK))) {
1722*fcf3ce44SJohn Forte 
1723*fcf3ce44SJohn Forte 			struct flock lk = {0};
1724*fcf3ce44SJohn Forte 			lk.l_type = (mode == CFG_RDLOCK ? F_RDLCK : F_WRLCK);
1725*fcf3ce44SJohn Forte 			lk.l_whence = SEEK_SET;
1726*fcf3ce44SJohn Forte 			lk.l_start = (off_t)0;
1727*fcf3ce44SJohn Forte 			lk.l_len = (off_t)0;
1728*fcf3ce44SJohn Forte 
1729*fcf3ce44SJohn Forte 			if (fcntl(cfg->cf[0].cf_lock, F_SETLKW, &lk) < 0)
1730*fcf3ce44SJohn Forte 				goto fail;
1731*fcf3ce44SJohn Forte 		}
1732*fcf3ce44SJohn Forte 	}
1733*fcf3ce44SJohn Forte 
1734*fcf3ce44SJohn Forte 	/* Determine number of files open */
1735*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
1736*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
1737*fcf3ce44SJohn Forte 		if ((cfp->cf_head) &&
1738*fcf3ce44SJohn Forte 		    (cfp->cf_head->h_state & CFG_HDR_INVALID)) {
1739*fcf3ce44SJohn Forte 			if ((rc = cfg_hdrcmp(cfp)) == 0) {
1740*fcf3ce44SJohn Forte #ifdef DEBUG_HDR
1741*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
1742*fcf3ce44SJohn Forte 			"cfg header match, skipping re-read\n");
1743*fcf3ce44SJohn Forte #endif
1744*fcf3ce44SJohn Forte 				cfp->cf_head->h_state |= CFG_HDR_RDLOCK;
1745*fcf3ce44SJohn Forte 				if (mode == CFG_WRLOCK)
1746*fcf3ce44SJohn Forte 					cfp->cf_head->h_state |= CFG_HDR_WRLOCK;
1747*fcf3ce44SJohn Forte 
1748*fcf3ce44SJohn Forte 				cfp->cf_head->h_state &= ~(CFG_HDR_INVALID);
1749*fcf3ce44SJohn Forte 				continue;
1750*fcf3ce44SJohn Forte 			}
1751*fcf3ce44SJohn Forte #ifdef DEBUG_HDR
1752*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "re-reading cfg, header mismatch\n");
1753*fcf3ce44SJohn Forte #endif
1754*fcf3ce44SJohn Forte 			/*
1755*fcf3ce44SJohn Forte 			 * dump what we have, info is stale
1756*fcf3ce44SJohn Forte 			 */
1757*fcf3ce44SJohn Forte 			cfg_free_cfglist(cfp);
1758*fcf3ce44SJohn Forte 			cfg_free_parser_tree();
1759*fcf3ce44SJohn Forte 
1760*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_ccopy1) {
1761*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_ccopy1);
1762*fcf3ce44SJohn Forte 				cfp->cf_head->h_ccopy1 = NULL;
1763*fcf3ce44SJohn Forte 			}
1764*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_ccopy2) {
1765*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_ccopy2);
1766*fcf3ce44SJohn Forte 				cfp->cf_head->h_ccopy2 = NULL;
1767*fcf3ce44SJohn Forte 			}
1768*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_sizes1) {
1769*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_sizes1);
1770*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes1 = NULL;
1771*fcf3ce44SJohn Forte 			}
1772*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_sizes2) {
1773*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_sizes2);
1774*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes2 = NULL;
1775*fcf3ce44SJohn Forte 			}
1776*fcf3ce44SJohn Forte 
1777*fcf3ce44SJohn Forte 			if (cfp->cf_head)
1778*fcf3ce44SJohn Forte 				free(cfp->cf_head);
1779*fcf3ce44SJohn Forte 			cfp->cf_head = NULL;
1780*fcf3ce44SJohn Forte 		}
1781*fcf3ce44SJohn Forte 
1782*fcf3ce44SJohn Forte 		if (cfp->cf_head == NULL) {
1783*fcf3ce44SJohn Forte 			if (!cfg_read(cfp)) {
1784*fcf3ce44SJohn Forte 				if (cfp->cf_head != NULL)
1785*fcf3ce44SJohn Forte 					cfg_init_header(cfp);
1786*fcf3ce44SJohn Forte 				else
1787*fcf3ce44SJohn Forte 					goto fail;
1788*fcf3ce44SJohn Forte 			} else {
1789*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1790*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1791*fcf3ce44SJohn Forte 				"reading parser config\n");
1792*fcf3ce44SJohn Forte #endif
1793*fcf3ce44SJohn Forte 				/* build parser trees */
1794*fcf3ce44SJohn Forte 				cfg_read_parser_config(cfp);
1795*fcf3ce44SJohn Forte 			}
1796*fcf3ce44SJohn Forte 
1797*fcf3ce44SJohn Forte 		}
1798*fcf3ce44SJohn Forte 		cfp->cf_head->h_state |= CFG_HDR_RDLOCK;
1799*fcf3ce44SJohn Forte 		if (mode == CFG_WRLOCK) {
1800*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_seq1 >= cfp->cf_head->h_seq2) {
1801*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1802*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1803*fcf3ce44SJohn Forte 					"cfg_lock: WRLOCK copying 1 to 2\n");
1804*fcf3ce44SJohn Forte #endif
1805*fcf3ce44SJohn Forte 				memcpy(cfp->cf_head->h_ccopy2,
1806*fcf3ce44SJohn Forte 					cfp->cf_head->h_ccopy1,
1807*fcf3ce44SJohn Forte 					cfp->cf_head->h_csize);
1808*fcf3ce44SJohn Forte 				memcpy(cfp->cf_head->h_sizes2,
1809*fcf3ce44SJohn Forte 					cfp->cf_head->h_sizes1,
1810*fcf3ce44SJohn Forte 					CFG_DEFAULT_PSIZE);
1811*fcf3ce44SJohn Forte 
1812*fcf3ce44SJohn Forte 				cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy2;
1813*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes = cfp->cf_head->h_sizes2;
1814*fcf3ce44SJohn Forte 			} else {
1815*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1816*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
1817*fcf3ce44SJohn Forte 					"cfg_lock: WRLOCK copying 2 to 1\n");
1818*fcf3ce44SJohn Forte #endif
1819*fcf3ce44SJohn Forte 				memcpy(cfp->cf_head->h_ccopy1,
1820*fcf3ce44SJohn Forte 					cfp->cf_head->h_ccopy2,
1821*fcf3ce44SJohn Forte 					cfp->cf_head->h_csize);
1822*fcf3ce44SJohn Forte 				memcpy(cfp->cf_head->h_sizes1,
1823*fcf3ce44SJohn Forte 					cfp->cf_head->h_sizes2,
1824*fcf3ce44SJohn Forte 					CFG_DEFAULT_PSIZE);
1825*fcf3ce44SJohn Forte 
1826*fcf3ce44SJohn Forte 				cfp->cf_head->h_cparse = cfp->cf_head->h_ccopy1;
1827*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes = cfp->cf_head->h_sizes1;
1828*fcf3ce44SJohn Forte 			}
1829*fcf3ce44SJohn Forte 
1830*fcf3ce44SJohn Forte 			cfp->cf_head->h_state |= CFG_HDR_WRLOCK;
1831*fcf3ce44SJohn Forte 		}
1832*fcf3ce44SJohn Forte 
1833*fcf3ce44SJohn Forte 		if (cfg_map_cfglists(cfp) < 0) {
1834*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1835*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "cfg: map_cfglists failed\n");
1836*fcf3ce44SJohn Forte #endif
1837*fcf3ce44SJohn Forte 			goto fail;
1838*fcf3ce44SJohn Forte 		}
1839*fcf3ce44SJohn Forte 
1840*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1841*fcf3ce44SJohn Forte 		dump_status(cfp, "cfg_lock");
1842*fcf3ce44SJohn Forte #endif
1843*fcf3ce44SJohn Forte 	}
1844*fcf3ce44SJohn Forte 
1845*fcf3ce44SJohn Forte 	return (TRUE);
1846*fcf3ce44SJohn Forte 
1847*fcf3ce44SJohn Forte fail:
1848*fcf3ce44SJohn Forte 	if (is_locked) {
1849*fcf3ce44SJohn Forte 		cfg_lockd_unlock();
1850*fcf3ce44SJohn Forte 	}
1851*fcf3ce44SJohn Forte 	cfg_perror_str = dgettext("cfg", CFG_EGENERIC);
1852*fcf3ce44SJohn Forte 	cfg_severity = CFG_ENONFATAL;
1853*fcf3ce44SJohn Forte 	return (FALSE);
1854*fcf3ce44SJohn Forte }
1855*fcf3ce44SJohn Forte 
1856*fcf3ce44SJohn Forte /*
1857*fcf3ce44SJohn Forte  * Unlock the database
1858*fcf3ce44SJohn Forte  */
1859*fcf3ce44SJohn Forte void
1860*fcf3ce44SJohn Forte cfp_unlock(cfp_t *cfp)
1861*fcf3ce44SJohn Forte {
1862*fcf3ce44SJohn Forte 
1863*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
1864*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_unlock\n");
1865*fcf3ce44SJohn Forte #endif
1866*fcf3ce44SJohn Forte 	if (cfg_lockd) {
1867*fcf3ce44SJohn Forte 		cfg_lockd_unlock();
1868*fcf3ce44SJohn Forte 	} else {
1869*fcf3ce44SJohn Forte 		struct flock lk = {0};
1870*fcf3ce44SJohn Forte 		lk.l_type = F_UNLCK;
1871*fcf3ce44SJohn Forte 		lk.l_whence = SEEK_SET;
1872*fcf3ce44SJohn Forte 		lk.l_start = (off_t)0;
1873*fcf3ce44SJohn Forte 		lk.l_len = (off_t)0;
1874*fcf3ce44SJohn Forte 		(void) fcntl(cfp->cf_lock, F_SETLKW, &lk);
1875*fcf3ce44SJohn Forte 	}
1876*fcf3ce44SJohn Forte 
1877*fcf3ce44SJohn Forte 	if (cfp->cf_head != NULL) {
1878*fcf3ce44SJohn Forte 		cfp->cf_head->h_state &= ~(CFG_HDR_RDLOCK|CFG_HDR_WRLOCK);
1879*fcf3ce44SJohn Forte 		cfp->cf_head->h_state |= CFG_HDR_INVALID;
1880*fcf3ce44SJohn Forte 	}
1881*fcf3ce44SJohn Forte }
1882*fcf3ce44SJohn Forte void
1883*fcf3ce44SJohn Forte cfg_unlock(CFGFILE *cfg)
1884*fcf3ce44SJohn Forte {
1885*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1886*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1887*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1888*fcf3ce44SJohn Forte 		return;
1889*fcf3ce44SJohn Forte 	}
1890*fcf3ce44SJohn Forte 
1891*fcf3ce44SJohn Forte 	cfp_unlock(&cfg->cf[0]);
1892*fcf3ce44SJohn Forte 	cfp_unlock(&cfg->cf[1]);
1893*fcf3ce44SJohn Forte }
1894*fcf3ce44SJohn Forte 
1895*fcf3ce44SJohn Forte /*
1896*fcf3ce44SJohn Forte  * Test for a read lock, set errno if failed.
1897*fcf3ce44SJohn Forte  */
1898*fcf3ce44SJohn Forte static int
1899*fcf3ce44SJohn Forte cfg_rdlock(CFGFILE *cfg)
1900*fcf3ce44SJohn Forte {
1901*fcf3ce44SJohn Forte 	int rc;
1902*fcf3ce44SJohn Forte 	cfp_t *cfp;
1903*fcf3ce44SJohn Forte 
1904*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1905*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1906*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1907*fcf3ce44SJohn Forte 		return (FALSE);
1908*fcf3ce44SJohn Forte 	}
1909*fcf3ce44SJohn Forte 
1910*fcf3ce44SJohn Forte 	/* Determine number of files open */
1911*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
1912*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
1913*fcf3ce44SJohn Forte 		if (cfp->cf_head == NULL) {
1914*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1915*fcf3ce44SJohn Forte 		    (void) fprintf(stderr, "cfg_rdlock: cf_head == NULL\n");
1916*fcf3ce44SJohn Forte #endif
1917*fcf3ce44SJohn Forte 		/*
1918*fcf3ce44SJohn Forte 		 * 6335583, if header == NULL,
1919*fcf3ce44SJohn Forte 		 * we can't call cfg_read to fill the header again
1920*fcf3ce44SJohn Forte 		 * since it will change the lock state to
1921*fcf3ce44SJohn Forte 		 * CFG_HDR_WRLOCK and dscfg will be the processer
1922*fcf3ce44SJohn Forte 		 * that hold the lock,
1923*fcf3ce44SJohn Forte 		 * just returning a FALSE if the case,
1924*fcf3ce44SJohn Forte 		 * then retrieve the lock state from flock structure.
1925*fcf3ce44SJohn Forte 		 */
1926*fcf3ce44SJohn Forte 		    rc = FALSE;
1927*fcf3ce44SJohn Forte 		    break;
1928*fcf3ce44SJohn Forte 		} else {
1929*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1930*fcf3ce44SJohn Forte 		    (void) fprintf(stderr, "cfg_rdlock: cf_head != NULL\n");
1931*fcf3ce44SJohn Forte #endif
1932*fcf3ce44SJohn Forte 		    if ((cfp->cf_head->h_state & CFG_HDR_RDLOCK)
1933*fcf3ce44SJohn Forte 			== CFG_HDR_RDLOCK)
1934*fcf3ce44SJohn Forte 			rc = TRUE;
1935*fcf3ce44SJohn Forte 		    else {
1936*fcf3ce44SJohn Forte 			rc = FALSE;
1937*fcf3ce44SJohn Forte 			break;
1938*fcf3ce44SJohn Forte 		    }
1939*fcf3ce44SJohn Forte 		}
1940*fcf3ce44SJohn Forte 	}
1941*fcf3ce44SJohn Forte 
1942*fcf3ce44SJohn Forte 	if (!rc)
1943*fcf3ce44SJohn Forte 		errno = EPERM;
1944*fcf3ce44SJohn Forte 
1945*fcf3ce44SJohn Forte 	return (rc);
1946*fcf3ce44SJohn Forte }
1947*fcf3ce44SJohn Forte 
1948*fcf3ce44SJohn Forte /*
1949*fcf3ce44SJohn Forte  * Test for a write lock, set errno if failed.
1950*fcf3ce44SJohn Forte  */
1951*fcf3ce44SJohn Forte static int
1952*fcf3ce44SJohn Forte cfg_wrlock(CFGFILE *cfg)
1953*fcf3ce44SJohn Forte {
1954*fcf3ce44SJohn Forte 	int rc;
1955*fcf3ce44SJohn Forte 	cfp_t *cfp;
1956*fcf3ce44SJohn Forte 
1957*fcf3ce44SJohn Forte 	if (cfg == NULL) {
1958*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
1959*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
1960*fcf3ce44SJohn Forte 		return (FALSE);
1961*fcf3ce44SJohn Forte 	}
1962*fcf3ce44SJohn Forte 
1963*fcf3ce44SJohn Forte 	/* Determine number of files open */
1964*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
1965*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
1966*fcf3ce44SJohn Forte 		if (cfp->cf_head == NULL) {
1967*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1968*fcf3ce44SJohn Forte 		    (void) fprintf(stderr, "cfg wrlock: cf_head == NULL\n");
1969*fcf3ce44SJohn Forte #endif
1970*fcf3ce44SJohn Forte 		/*
1971*fcf3ce44SJohn Forte 		 * 6335583, see comments on cfg_rdlock
1972*fcf3ce44SJohn Forte 		 */
1973*fcf3ce44SJohn Forte 		    rc = FALSE;
1974*fcf3ce44SJohn Forte 		    break;
1975*fcf3ce44SJohn Forte 		} else {
1976*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
1977*fcf3ce44SJohn Forte 		    (void) fprintf(stderr, "cfg wrlock: cf_head != NULL\n");
1978*fcf3ce44SJohn Forte #endif
1979*fcf3ce44SJohn Forte 		    if ((cfp->cf_head->h_state & CFG_HDR_WRLOCK)
1980*fcf3ce44SJohn Forte 			== CFG_HDR_WRLOCK)
1981*fcf3ce44SJohn Forte 			rc = TRUE;
1982*fcf3ce44SJohn Forte 		    else {
1983*fcf3ce44SJohn Forte 			rc = FALSE;
1984*fcf3ce44SJohn Forte 			break;
1985*fcf3ce44SJohn Forte 		    }
1986*fcf3ce44SJohn Forte 		}
1987*fcf3ce44SJohn Forte 	}
1988*fcf3ce44SJohn Forte 
1989*fcf3ce44SJohn Forte 	if (!rc)
1990*fcf3ce44SJohn Forte 		errno = EPERM;
1991*fcf3ce44SJohn Forte 
1992*fcf3ce44SJohn Forte 	return (rc);
1993*fcf3ce44SJohn Forte }
1994*fcf3ce44SJohn Forte 
1995*fcf3ce44SJohn Forte /*
1996*fcf3ce44SJohn Forte  * cfg_get_lock
1997*fcf3ce44SJohn Forte  * Find lock status of CFG database.
1998*fcf3ce44SJohn Forte  * Returns: TRUE and sets lock and pid if the lock is held, FALSE otherwise.
1999*fcf3ce44SJohn Forte  */
2000*fcf3ce44SJohn Forte int
2001*fcf3ce44SJohn Forte cfg_get_lock(CFGFILE *cfg, CFGLOCK *lock, pid_t *pid)
2002*fcf3ce44SJohn Forte {
2003*fcf3ce44SJohn Forte 	struct flock lk;
2004*fcf3ce44SJohn Forte 	int rc;
2005*fcf3ce44SJohn Forte 
2006*fcf3ce44SJohn Forte 	if (cfg == NULL) {
2007*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
2008*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2009*fcf3ce44SJohn Forte 		return (FALSE);
2010*fcf3ce44SJohn Forte 	}
2011*fcf3ce44SJohn Forte 
2012*fcf3ce44SJohn Forte 	if (cfg_lockd) {
2013*fcf3ce44SJohn Forte 		switch (cfg_lockedby(pid)) {
2014*fcf3ce44SJohn Forte 		case LOCK_READ:
2015*fcf3ce44SJohn Forte 			*lock = CFG_RDLOCK;
2016*fcf3ce44SJohn Forte 			return (TRUE);
2017*fcf3ce44SJohn Forte 		case LOCK_WRITE:
2018*fcf3ce44SJohn Forte 			*lock = CFG_WRLOCK;
2019*fcf3ce44SJohn Forte 			return (TRUE);
2020*fcf3ce44SJohn Forte 		case LOCK_NOTLOCKED:
2021*fcf3ce44SJohn Forte 		default:
2022*fcf3ce44SJohn Forte 			return (FALSE);
2023*fcf3ce44SJohn Forte 		}
2024*fcf3ce44SJohn Forte 	} else {
2025*fcf3ce44SJohn Forte 		if (cfg_wrlock(cfg)) {
2026*fcf3ce44SJohn Forte 		    *lock = CFG_WRLOCK;
2027*fcf3ce44SJohn Forte 		    *pid = getpid();
2028*fcf3ce44SJohn Forte 		    return (TRUE);
2029*fcf3ce44SJohn Forte 		}
2030*fcf3ce44SJohn Forte 
2031*fcf3ce44SJohn Forte 		if (cfg_rdlock(cfg)) {
2032*fcf3ce44SJohn Forte 		    *lock = CFG_RDLOCK;
2033*fcf3ce44SJohn Forte 		    *pid = getpid();
2034*fcf3ce44SJohn Forte 		    return (TRUE);
2035*fcf3ce44SJohn Forte 		}
2036*fcf3ce44SJohn Forte 	}
2037*fcf3ce44SJohn Forte 	/* Lock is always based on local file pointer */
2038*fcf3ce44SJohn Forte 	cfg->cf[1].cf_lock = cfg->cf[0].cf_lock = cfg->cf[0].cf_fd;
2039*fcf3ce44SJohn Forte 
2040*fcf3ce44SJohn Forte 	bzero(&lk, sizeof (lk));
2041*fcf3ce44SJohn Forte 	lk.l_type = F_WRLCK;
2042*fcf3ce44SJohn Forte 	lk.l_whence = SEEK_SET;
2043*fcf3ce44SJohn Forte 	lk.l_start = (off_t)0;
2044*fcf3ce44SJohn Forte 	lk.l_len = (off_t)0;
2045*fcf3ce44SJohn Forte 
2046*fcf3ce44SJohn Forte 	if (fcntl(cfg->cf[0].cf_lock, F_GETLK, &lk) < 0)
2047*fcf3ce44SJohn Forte 		rc = FALSE;
2048*fcf3ce44SJohn Forte 	else {
2049*fcf3ce44SJohn Forte 		if (lk.l_type == F_UNLCK)
2050*fcf3ce44SJohn Forte 			rc = FALSE;
2051*fcf3ce44SJohn Forte 		else {
2052*fcf3ce44SJohn Forte 			rc = TRUE;
2053*fcf3ce44SJohn Forte 			*pid = lk.l_pid;
2054*fcf3ce44SJohn Forte 			*lock = lk.l_type == F_WRLCK ? CFG_WRLOCK : CFG_RDLOCK;
2055*fcf3ce44SJohn Forte 		}
2056*fcf3ce44SJohn Forte 	}
2057*fcf3ce44SJohn Forte 
2058*fcf3ce44SJohn Forte 	return (rc);
2059*fcf3ce44SJohn Forte }
2060*fcf3ce44SJohn Forte 
2061*fcf3ce44SJohn Forte /*
2062*fcf3ce44SJohn Forte  * cfg_commit
2063*fcf3ce44SJohn Forte  * Write modified version of header, configuration and persistent
2064*fcf3ce44SJohn Forte  * data using 2 stage commit.
2065*fcf3ce44SJohn Forte  * If no valid data is found in header, it is assumed to be an initial
2066*fcf3ce44SJohn Forte  * write and we will create the default header (could be dangerous)
2067*fcf3ce44SJohn Forte  * another tricky part, if we are doing an upgrade we may be dealing
2068*fcf3ce44SJohn Forte  * with an old database. we need to take care seeking and writing
2069*fcf3ce44SJohn Forte  * until such time that it is upgraded.
2070*fcf3ce44SJohn Forte  *
2071*fcf3ce44SJohn Forte  * Mutual exclusion is checked using cfg_lock
2072*fcf3ce44SJohn Forte  */
2073*fcf3ce44SJohn Forte 
2074*fcf3ce44SJohn Forte int
2075*fcf3ce44SJohn Forte cfg_commit(CFGFILE *cfg)
2076*fcf3ce44SJohn Forte {
2077*fcf3ce44SJohn Forte 	cfp_t *cfp;
2078*fcf3ce44SJohn Forte 	int rc;
2079*fcf3ce44SJohn Forte 	time_t tloc;
2080*fcf3ce44SJohn Forte 	int section;
2081*fcf3ce44SJohn Forte 	int wrsize, *ip;
2082*fcf3ce44SJohn Forte 
2083*fcf3ce44SJohn Forte 	if (cfg == NULL) {
2084*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
2085*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2086*fcf3ce44SJohn Forte 		return (FALSE);
2087*fcf3ce44SJohn Forte 	}
2088*fcf3ce44SJohn Forte 
2089*fcf3ce44SJohn Forte 	if (!cfg_wrlock(cfg))
2090*fcf3ce44SJohn Forte 		return (FALSE);
2091*fcf3ce44SJohn Forte 
2092*fcf3ce44SJohn Forte 	/* Determine number of files open */
2093*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
2094*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
2095*fcf3ce44SJohn Forte 
2096*fcf3ce44SJohn Forte 		/*
2097*fcf3ce44SJohn Forte 		 * lets put everything back into one char *
2098*fcf3ce44SJohn Forte 		 */
2099*fcf3ce44SJohn Forte 		cfg_replace_lists(cfp);
2100*fcf3ce44SJohn Forte 
2101*fcf3ce44SJohn Forte 		if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
2102*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
2103*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: seek header failed\n");
2104*fcf3ce44SJohn Forte #endif
2105*fcf3ce44SJohn Forte 			return (FALSE);
2106*fcf3ce44SJohn Forte 		}
2107*fcf3ce44SJohn Forte 
2108*fcf3ce44SJohn Forte 		cfp->cf_head->h_size = cfp->cf_head->h_parsesize
2109*fcf3ce44SJohn Forte 			+ cfp->cf_head->h_csize + cfp->cf_head->h_psize;
2110*fcf3ce44SJohn Forte 		cfp->cf_head->h_stamp = time(&tloc);
2111*fcf3ce44SJohn Forte 
2112*fcf3ce44SJohn Forte 		/* seeking into database */
2113*fcf3ce44SJohn Forte 		if ((*cfp->cf_pp->seek)
2114*fcf3ce44SJohn Forte 			(cfp, sizeof (cfgheader_t), SEEK_CUR) < 0)
2115*fcf3ce44SJohn Forte 			return (FALSE);
2116*fcf3ce44SJohn Forte 
2117*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_ccopy1 == cfp->cf_head->h_cparse) {
2118*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_seq1 < 0)
2119*fcf3ce44SJohn Forte 				cfp->cf_head->h_seq1 = 1;
2120*fcf3ce44SJohn Forte 			else
2121*fcf3ce44SJohn Forte 				cfp->cf_head->h_seq1 = cfp->cf_head->h_seq2 + 1;
2122*fcf3ce44SJohn Forte 			section = 1;
2123*fcf3ce44SJohn Forte 		} else {
2124*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_seq2 < 0)
2125*fcf3ce44SJohn Forte 				cfp->cf_head->h_seq2 = 1;
2126*fcf3ce44SJohn Forte 			else
2127*fcf3ce44SJohn Forte 				cfp->cf_head->h_seq2 = cfp->cf_head->h_seq1 + 1;
2128*fcf3ce44SJohn Forte 			section = 2;
2129*fcf3ce44SJohn Forte 		}
2130*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
2131*fcf3ce44SJohn Forte 		dump_status(cfp, "cfg_commit");
2132*fcf3ce44SJohn Forte #endif
2133*fcf3ce44SJohn Forte 		rc = (*cfp->cf_pp->write)
2134*fcf3ce44SJohn Forte 			(cfp, cfp->cf_mapped, CFG_DEFAULT_PARSE_SIZE);
2135*fcf3ce44SJohn Forte #ifdef DEBUG
2136*fcf3ce44SJohn Forte 		if (rc < 0) {
2137*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2138*fcf3ce44SJohn Forte 				"parse commit: rc %d h_parsesize %d\n",
2139*fcf3ce44SJohn Forte 				rc, cfp->cf_head->h_parsesize);
2140*fcf3ce44SJohn Forte 		}
2141*fcf3ce44SJohn Forte #endif
2142*fcf3ce44SJohn Forte 		if (section == 1) {
2143*fcf3ce44SJohn Forte 			rc = (*cfp->cf_pp->write)
2144*fcf3ce44SJohn Forte 				(cfp, cfp->cf_head->h_ccopy1,
2145*fcf3ce44SJohn Forte 				cfp->cf_head->h_csize);
2146*fcf3ce44SJohn Forte #ifdef DEBUG
2147*fcf3ce44SJohn Forte 			if (rc < 0) {
2148*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
2149*fcf3ce44SJohn Forte 					"csection commit 1: rc %d h_csize %d\n",
2150*fcf3ce44SJohn Forte 					rc, cfp->cf_head->h_csize);
2151*fcf3ce44SJohn Forte 			}
2152*fcf3ce44SJohn Forte #endif
2153*fcf3ce44SJohn Forte 			if ((*cfp->cf_pp->seek)
2154*fcf3ce44SJohn Forte 			    (cfp, (2 * CFG_DEFAULT_SSIZE) - rc, SEEK_CUR) < 0)
2155*fcf3ce44SJohn Forte 				return (FALSE);
2156*fcf3ce44SJohn Forte 
2157*fcf3ce44SJohn Forte 			/*
2158*fcf3ce44SJohn Forte 			 * limit the write to only what we need
2159*fcf3ce44SJohn Forte 			 */
2160*fcf3ce44SJohn Forte 			ip = cfp->cf_head->h_sizes1;
2161*fcf3ce44SJohn Forte 			for (wrsize = 0; *ip; ip += *ip + 1)
2162*fcf3ce44SJohn Forte 				wrsize += *ip + 1;
2163*fcf3ce44SJohn Forte 
2164*fcf3ce44SJohn Forte 			rc = (*cfp->cf_pp->write)(cfp,
2165*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes1, wrsize * sizeof (int));
2166*fcf3ce44SJohn Forte #ifdef DEBUG
2167*fcf3ce44SJohn Forte 			if (rc < 0) {
2168*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
2169*fcf3ce44SJohn Forte 					"cfg: write list sizes1 failed rc\n");
2170*fcf3ce44SJohn Forte 			}
2171*fcf3ce44SJohn Forte #endif
2172*fcf3ce44SJohn Forte 		} else {
2173*fcf3ce44SJohn Forte 			if ((*cfp->cf_pp->seek)(cfp,
2174*fcf3ce44SJohn Forte 				CFG_DEFAULT_SSIZE, SEEK_CUR) < 0)
2175*fcf3ce44SJohn Forte 				return (FALSE);
2176*fcf3ce44SJohn Forte 
2177*fcf3ce44SJohn Forte 			rc = (*cfp->cf_pp->write)(cfp,
2178*fcf3ce44SJohn Forte 				cfp->cf_head->h_ccopy2, cfp->cf_head->h_csize);
2179*fcf3ce44SJohn Forte #ifdef DEBUG
2180*fcf3ce44SJohn Forte 			if (rc < 0) {
2181*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
2182*fcf3ce44SJohn Forte 					"csection commit 2: rc %d h_csize %d\n",
2183*fcf3ce44SJohn Forte 					rc, cfp->cf_head->h_csize);
2184*fcf3ce44SJohn Forte 			}
2185*fcf3ce44SJohn Forte #endif
2186*fcf3ce44SJohn Forte 			if ((*cfp->cf_pp->seek)
2187*fcf3ce44SJohn Forte 			    (cfp, (CFG_DEFAULT_SSIZE + CFG_DEFAULT_PSIZE) - rc,
2188*fcf3ce44SJohn Forte 			    SEEK_CUR) < 0)
2189*fcf3ce44SJohn Forte 				return (FALSE);
2190*fcf3ce44SJohn Forte 
2191*fcf3ce44SJohn Forte 			/*
2192*fcf3ce44SJohn Forte 			 * limit the write to only what we need
2193*fcf3ce44SJohn Forte 			 */
2194*fcf3ce44SJohn Forte 			ip = cfp->cf_head->h_sizes2;
2195*fcf3ce44SJohn Forte 			for (wrsize = 0; *ip; ip += *ip + 1)
2196*fcf3ce44SJohn Forte 				wrsize += *ip + 1;
2197*fcf3ce44SJohn Forte 
2198*fcf3ce44SJohn Forte 			rc = (*cfp->cf_pp->write)(cfp, cfp->cf_head->h_sizes2,
2199*fcf3ce44SJohn Forte 				wrsize * sizeof (int));
2200*fcf3ce44SJohn Forte #ifdef DEBUG
2201*fcf3ce44SJohn Forte 			if (rc < 0) {
2202*fcf3ce44SJohn Forte 				(void) fprintf(stderr,
2203*fcf3ce44SJohn Forte 					"cfg: write list sizes2 failed\n");
2204*fcf3ce44SJohn Forte 			}
2205*fcf3ce44SJohn Forte #endif
2206*fcf3ce44SJohn Forte 
2207*fcf3ce44SJohn Forte 		}
2208*fcf3ce44SJohn Forte 
2209*fcf3ce44SJohn Forte 
2210*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2211*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
2212*fcf3ce44SJohn Forte 		    "writing h_csize %d\n", cfp->cf_head->h_csize);
2213*fcf3ce44SJohn Forte #endif
2214*fcf3ce44SJohn Forte 		if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0)
2215*fcf3ce44SJohn Forte 			return (FALSE);
2216*fcf3ce44SJohn Forte 
2217*fcf3ce44SJohn Forte 		cfp->cf_head->h_size = cfp->cf_head->h_parsesize +
2218*fcf3ce44SJohn Forte 			cfp->cf_head->h_csize +	cfp->cf_head->h_psize;
2219*fcf3ce44SJohn Forte 
2220*fcf3ce44SJohn Forte 		rc = (*cfp->cf_pp->write)
2221*fcf3ce44SJohn Forte 			(cfp, cfp->cf_head, sizeof (cfgheader_t));
2222*fcf3ce44SJohn Forte 		if (rc < 0) {
2223*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2224*fcf3ce44SJohn Forte 				"cfg_commit: header write failed");
2225*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2226*fcf3ce44SJohn Forte 			return (FALSE);
2227*fcf3ce44SJohn Forte 		}
2228*fcf3ce44SJohn Forte 	}
2229*fcf3ce44SJohn Forte 
2230*fcf3ce44SJohn Forte 	return (TRUE);
2231*fcf3ce44SJohn Forte }
2232*fcf3ce44SJohn Forte 
2233*fcf3ce44SJohn Forte /*
2234*fcf3ce44SJohn Forte  * cfg_rewind
2235*fcf3ce44SJohn Forte  * rewind internal file pointer for specified section
2236*fcf3ce44SJohn Forte  * empty now, rewind not necessary. But don't break
2237*fcf3ce44SJohn Forte  * old code.
2238*fcf3ce44SJohn Forte  */
2239*fcf3ce44SJohn Forte /*ARGSUSED*/
2240*fcf3ce44SJohn Forte void
2241*fcf3ce44SJohn Forte cfg_rewind(CFGFILE *cfg, int section)
2242*fcf3ce44SJohn Forte {
2243*fcf3ce44SJohn Forte 	switch (section) {
2244*fcf3ce44SJohn Forte 		case CFG_SEC_CONF:
2245*fcf3ce44SJohn Forte 			break;
2246*fcf3ce44SJohn Forte 		case CFG_SEC_ALL:
2247*fcf3ce44SJohn Forte 			break;
2248*fcf3ce44SJohn Forte 	};
2249*fcf3ce44SJohn Forte }
2250*fcf3ce44SJohn Forte 
2251*fcf3ce44SJohn Forte /*
2252*fcf3ce44SJohn Forte  * cfg_location
2253*fcf3ce44SJohn Forte  * set or return the default location file to
2254*fcf3ce44SJohn Forte  * determine the partition name of the configuration partition
2255*fcf3ce44SJohn Forte  * location is stored in well known file location
2256*fcf3ce44SJohn Forte  */
2257*fcf3ce44SJohn Forte char *
2258*fcf3ce44SJohn Forte cfg_location(char *location, int mode, char *altroot)
2259*fcf3ce44SJohn Forte {
2260*fcf3ce44SJohn Forte 	int fd;
2261*fcf3ce44SJohn Forte 	int fmode;
2262*fcf3ce44SJohn Forte 	int rc;
2263*fcf3ce44SJohn Forte 	char wellknown[NSC_MAXPATH];
2264*fcf3ce44SJohn Forte 	char loc[NSC_MAXPATH];
2265*fcf3ce44SJohn Forte 
2266*fcf3ce44SJohn Forte 	if (mode == CFG_LOC_GET_LOCAL) {
2267*fcf3ce44SJohn Forte 		return (CFG_LOCAL_LOCATION);
2268*fcf3ce44SJohn Forte 	} else if (mode == CFG_LOC_GET_CLUSTER) {
2269*fcf3ce44SJohn Forte 		fmode = O_RDONLY;
2270*fcf3ce44SJohn Forte 	} else {
2271*fcf3ce44SJohn Forte 		fmode = O_RDWR | O_CREAT;
2272*fcf3ce44SJohn Forte 	}
2273*fcf3ce44SJohn Forte 
2274*fcf3ce44SJohn Forte 	if (altroot) {
2275*fcf3ce44SJohn Forte 		strcpy(wellknown, altroot);
2276*fcf3ce44SJohn Forte 		strcat(wellknown, CFG_CLUSTER_LOCATION);
2277*fcf3ce44SJohn Forte 	} else
2278*fcf3ce44SJohn Forte 		strcpy(wellknown, CFG_CLUSTER_LOCATION);
2279*fcf3ce44SJohn Forte 
2280*fcf3ce44SJohn Forte 	fd = open(wellknown, fmode, 0644);
2281*fcf3ce44SJohn Forte 	if (fd < 0) {
2282*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", strerror(errno));
2283*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
2284*fcf3ce44SJohn Forte 		return (NULL);
2285*fcf3ce44SJohn Forte 	}
2286*fcf3ce44SJohn Forte 
2287*fcf3ce44SJohn Forte 	if (mode == CFG_LOC_SET_CLUSTER) {
2288*fcf3ce44SJohn Forte 		if (location == NULL || (strlen(location) > NSC_MAXPATH)) {
2289*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2290*fcf3ce44SJohn Forte 			    "cfg_location: filename too big or missing");
2291*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2292*fcf3ce44SJohn Forte 			return (NULL);
2293*fcf3ce44SJohn Forte 		}
2294*fcf3ce44SJohn Forte 
2295*fcf3ce44SJohn Forte 		/*
2296*fcf3ce44SJohn Forte 		 * 5082142
2297*fcf3ce44SJohn Forte 		 * If we're in a cluster, make sure that the config location
2298*fcf3ce44SJohn Forte 		 * is a raw device.  Using non-raw did devices in a cluster
2299*fcf3ce44SJohn Forte 		 * can result in data corruption, since inconsistent data
2300*fcf3ce44SJohn Forte 		 * may reside in the block cache on one node, but has not
2301*fcf3ce44SJohn Forte 		 * been flushed to disk.
2302*fcf3ce44SJohn Forte 		 */
2303*fcf3ce44SJohn Forte 		if (cfg_iscluster() > 0) {
2304*fcf3ce44SJohn Forte 			struct stat dscfg_stat;
2305*fcf3ce44SJohn Forte 			if (stat(location, &dscfg_stat) != 0) {
2306*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg",
2307*fcf3ce44SJohn Forte 				    "Unable to access dscfg location");
2308*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
2309*fcf3ce44SJohn Forte 				return (NULL);
2310*fcf3ce44SJohn Forte 			}
2311*fcf3ce44SJohn Forte 			if (!S_ISCHR(dscfg_stat.st_mode)) {
2312*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg",
2313*fcf3ce44SJohn Forte 				    "dscfg location must be a raw device");
2314*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
2315*fcf3ce44SJohn Forte 				return (NULL);
2316*fcf3ce44SJohn Forte 			}
2317*fcf3ce44SJohn Forte 		}
2318*fcf3ce44SJohn Forte 
2319*fcf3ce44SJohn Forte 		if (ftruncate(fd, 0) < 0)
2320*fcf3ce44SJohn Forte 			return (NULL);
2321*fcf3ce44SJohn Forte 
2322*fcf3ce44SJohn Forte 		rc = write(fd, location, strlen(location));
2323*fcf3ce44SJohn Forte 		if (rc < 0) {
2324*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2325*fcf3ce44SJohn Forte 			    "cfg_location: write to well known failed");
2326*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2327*fcf3ce44SJohn Forte 			return (NULL);
2328*fcf3ce44SJohn Forte 		}
2329*fcf3ce44SJohn Forte 		bzero(config_file, sizeof (config_file));
2330*fcf3ce44SJohn Forte 	}
2331*fcf3ce44SJohn Forte 	if (lseek(fd, 0, SEEK_SET) < 0)
2332*fcf3ce44SJohn Forte 		return (NULL);
2333*fcf3ce44SJohn Forte 
2334*fcf3ce44SJohn Forte 	bzero(config_file, sizeof (config_file));
2335*fcf3ce44SJohn Forte 	rc = read(fd, config_file, sizeof (config_file));
2336*fcf3ce44SJohn Forte 	if (rc < 0) {
2337*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg",
2338*fcf3ce44SJohn Forte 		    "cfg_location: read from well known failed");
2339*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2340*fcf3ce44SJohn Forte 		return (NULL);
2341*fcf3ce44SJohn Forte 	}
2342*fcf3ce44SJohn Forte 	close(fd);
2343*fcf3ce44SJohn Forte 	if (altroot) {
2344*fcf3ce44SJohn Forte 		strcpy(loc, altroot);
2345*fcf3ce44SJohn Forte 		strcat(loc, config_file);
2346*fcf3ce44SJohn Forte 		bzero(config_file, sizeof (config_file));
2347*fcf3ce44SJohn Forte 		strcpy(config_file, loc);
2348*fcf3ce44SJohn Forte 	}
2349*fcf3ce44SJohn Forte 
2350*fcf3ce44SJohn Forte 	/*
2351*fcf3ce44SJohn Forte 	 * scan string out of config_file, to strip whitespace
2352*fcf3ce44SJohn Forte 	 */
2353*fcf3ce44SJohn Forte 	sscanf(config_file, "%s", loc);
2354*fcf3ce44SJohn Forte 	strcpy(config_file, loc);
2355*fcf3ce44SJohn Forte 
2356*fcf3ce44SJohn Forte 	return (config_file);
2357*fcf3ce44SJohn Forte }
2358*fcf3ce44SJohn Forte 
2359*fcf3ce44SJohn Forte /*
2360*fcf3ce44SJohn Forte  * cfg_update_parser_config
2361*fcf3ce44SJohn Forte  * If tag and key exist return -1
2362*fcf3ce44SJohn Forte  *
2363*fcf3ce44SJohn Forte  * XXX Currently does not append new field to existing parser rule
2364*fcf3ce44SJohn Forte  */
2365*fcf3ce44SJohn Forte 
2366*fcf3ce44SJohn Forte int
2367*fcf3ce44SJohn Forte cfg_update_parser_config(CFGFILE *cfg, const char *key, int section)
2368*fcf3ce44SJohn Forte {
2369*fcf3ce44SJohn Forte 	cfp_t *cfp;
2370*fcf3ce44SJohn Forte 	int size;
2371*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
2372*fcf3ce44SJohn Forte 	struct parser *tbl;
2373*fcf3ce44SJohn Forte 	char tmpkey[CFG_MAX_KEY];
2374*fcf3ce44SJohn Forte 	char *ky, *fld;
2375*fcf3ce44SJohn Forte 	errno = 0;
2376*fcf3ce44SJohn Forte 
2377*fcf3ce44SJohn Forte 	if (cfg == NULL) {
2378*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
2379*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2380*fcf3ce44SJohn Forte 		return (-1);
2381*fcf3ce44SJohn Forte 	}
2382*fcf3ce44SJohn Forte 
2383*fcf3ce44SJohn Forte 	cfp = FP_SUN_CLUSTER(cfg);
2384*fcf3ce44SJohn Forte 	if (!cfg_wrlock(cfg))
2385*fcf3ce44SJohn Forte 		return (-1);
2386*fcf3ce44SJohn Forte 
2387*fcf3ce44SJohn Forte 	bzero(buf, CFG_MAX_BUF);
2388*fcf3ce44SJohn Forte 	bzero(tmpkey, sizeof (tmpkey));
2389*fcf3ce44SJohn Forte 	strcpy(tmpkey, key);
2390*fcf3ce44SJohn Forte 	if (section == CFG_PARSE_CONF) {
2391*fcf3ce44SJohn Forte 		strcat(buf, "C:");
2392*fcf3ce44SJohn Forte 		tbl =  chead;
2393*fcf3ce44SJohn Forte 	} else {
2394*fcf3ce44SJohn Forte 		errno = EINVAL;
2395*fcf3ce44SJohn Forte 		return (-1);
2396*fcf3ce44SJohn Forte 	}
2397*fcf3ce44SJohn Forte 	ky = strtok(tmpkey, ".");
2398*fcf3ce44SJohn Forte 	fld = strtok(NULL, ".");
2399*fcf3ce44SJohn Forte 	while (fld) {
2400*fcf3ce44SJohn Forte 		size = cfg_get_item(tbl, ky, fld);
2401*fcf3ce44SJohn Forte 
2402*fcf3ce44SJohn Forte 		/*
2403*fcf3ce44SJohn Forte 		 * Assure we are loading a clean table, with do duplicates
2404*fcf3ce44SJohn Forte 		 * based on our File Descriptor
2405*fcf3ce44SJohn Forte 		 */
2406*fcf3ce44SJohn Forte 		if (chead_loaded && (chead_loaded != cfp->cf_fd)) {
2407*fcf3ce44SJohn Forte 			if (size <= 0)
2408*fcf3ce44SJohn Forte 				return (-1);
2409*fcf3ce44SJohn Forte 		} else {
2410*fcf3ce44SJohn Forte 			if (size > 0)
2411*fcf3ce44SJohn Forte 				return (-1);
2412*fcf3ce44SJohn Forte 		}
2413*fcf3ce44SJohn Forte 		fld = strtok(NULL, ".");
2414*fcf3ce44SJohn Forte 	}
2415*fcf3ce44SJohn Forte 	size = strlen(key) + 2;
2416*fcf3ce44SJohn Forte 	strncat(buf, key, size);
2417*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
2418*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "update parser config %s size %d\n", buf, size);
2419*fcf3ce44SJohn Forte #endif
2420*fcf3ce44SJohn Forte 	if ((size + cfp->cf_head->h_parseoff) > CFG_DEFAULT_PARSE_SIZE) {
2421*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg",
2422*fcf3ce44SJohn Forte 		    "cfg_update_parser_config: header overrun");
2423*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2424*fcf3ce44SJohn Forte #ifdef DEBUG_LIB
2425*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "update parser config: "
2426*fcf3ce44SJohn Forte 		    "overrun siz %d poff %d parsesize %d\n",
2427*fcf3ce44SJohn Forte 		    size, cfp->cf_head->h_parseoff, cfp->cf_head->h_parsesize);
2428*fcf3ce44SJohn Forte #endif
2429*fcf3ce44SJohn Forte 		errno = E2BIG;
2430*fcf3ce44SJohn Forte 		return (-1);
2431*fcf3ce44SJohn Forte 	}
2432*fcf3ce44SJohn Forte 	bcopy(buf, (cfp->cf_mapped + cfp->cf_head->h_parseoff), size);
2433*fcf3ce44SJohn Forte 	cfp->cf_head->h_parseoff += size;
2434*fcf3ce44SJohn Forte 	cfp->cf_head->h_state |= CFG_HDR_INVALID;
2435*fcf3ce44SJohn Forte 	if (cfp->cf_mapped[cfp->cf_head->h_parseoff - 1] != '\n') {
2436*fcf3ce44SJohn Forte 		cfp->cf_mapped[cfp->cf_head->h_parseoff] = '\n';
2437*fcf3ce44SJohn Forte 		cfp->cf_head->h_parseoff++;
2438*fcf3ce44SJohn Forte 	}
2439*fcf3ce44SJohn Forte 	cfp->cf_head->h_parsesize = cfp->cf_head->h_parseoff;
2440*fcf3ce44SJohn Forte 	cfg_read_parser_config(cfp);
2441*fcf3ce44SJohn Forte 	return (TRUE);
2442*fcf3ce44SJohn Forte }
2443*fcf3ce44SJohn Forte /*
2444*fcf3ce44SJohn Forte  * cfg_read_parser_config
2445*fcf3ce44SJohn Forte  * reads parser config from file
2446*fcf3ce44SJohn Forte  * converts it to internal tree for parsing
2447*fcf3ce44SJohn Forte  * chead for configuration parser entries
2448*fcf3ce44SJohn Forte  *
2449*fcf3ce44SJohn Forte  */
2450*fcf3ce44SJohn Forte static
2451*fcf3ce44SJohn Forte void
2452*fcf3ce44SJohn Forte cfg_read_parser_config(cfp_t *cfp)
2453*fcf3ce44SJohn Forte {
2454*fcf3ce44SJohn Forte 	struct lookup *p, *q;
2455*fcf3ce44SJohn Forte 	struct parser *thead;
2456*fcf3ce44SJohn Forte 	int off, foff;
2457*fcf3ce44SJohn Forte 	char *part;
2458*fcf3ce44SJohn Forte 	char *key;
2459*fcf3ce44SJohn Forte 	char *fld;
2460*fcf3ce44SJohn Forte 	int fldnum;
2461*fcf3ce44SJohn Forte 	char c;
2462*fcf3ce44SJohn Forte 	char buf[CFG_MAX_BUF];
2463*fcf3ce44SJohn Forte 	int i = 0;
2464*fcf3ce44SJohn Forte 	int n = 0;
2465*fcf3ce44SJohn Forte 
2466*fcf3ce44SJohn Forte 	off = foff = 0;
2467*fcf3ce44SJohn Forte 	/*CONSTCOND*/
2468*fcf3ce44SJohn Forte 	while (TRUE) {
2469*fcf3ce44SJohn Forte 		off = 0;
2470*fcf3ce44SJohn Forte 		bzero(buf, CFG_MAX_BUF);
2471*fcf3ce44SJohn Forte 		/* LINTED it assigns value to c */
2472*fcf3ce44SJohn Forte 		while (c = cfp->cf_mapped[foff++]) {
2473*fcf3ce44SJohn Forte 			if (c == '\n')
2474*fcf3ce44SJohn Forte 				break;
2475*fcf3ce44SJohn Forte 			buf[off++] = c;
2476*fcf3ce44SJohn Forte 		}
2477*fcf3ce44SJohn Forte 		part = strtok(buf, ":");
2478*fcf3ce44SJohn Forte 		if (!part)
2479*fcf3ce44SJohn Forte 			break;
2480*fcf3ce44SJohn Forte 		if (*part == 'C') {
2481*fcf3ce44SJohn Forte 			thead = chead;
2482*fcf3ce44SJohn Forte 			n = i;
2483*fcf3ce44SJohn Forte 		}
2484*fcf3ce44SJohn Forte 		key = strtok(NULL, ".");
2485*fcf3ce44SJohn Forte 		if (!key)
2486*fcf3ce44SJohn Forte 			break;
2487*fcf3ce44SJohn Forte 		strcpy(thead[n].tag.l_word, key);
2488*fcf3ce44SJohn Forte 		thead[n].tag.l_value = 0;
2489*fcf3ce44SJohn Forte 		thead[n].fld = NULL;
2490*fcf3ce44SJohn Forte 		fldnum = 1;
2491*fcf3ce44SJohn Forte 		while ((fld = strtok(NULL, ".")) != NULL) {
2492*fcf3ce44SJohn Forte 			p = thead[n].fld;
2493*fcf3ce44SJohn Forte 			if (p == NULL) {
2494*fcf3ce44SJohn Forte 				q = thead[n].fld = calloc(1,
2495*fcf3ce44SJohn Forte 						sizeof (struct lookup));
2496*fcf3ce44SJohn Forte 			} else {
2497*fcf3ce44SJohn Forte 				for (q = thead[n].fld; q; q = q->l_next)
2498*fcf3ce44SJohn Forte 					p = q;
2499*fcf3ce44SJohn Forte 				q = calloc(1, sizeof (struct lookup));
2500*fcf3ce44SJohn Forte 				p->l_next = q;
2501*fcf3ce44SJohn Forte 			}
2502*fcf3ce44SJohn Forte 			strcpy(q->l_word, fld);
2503*fcf3ce44SJohn Forte 			q->l_value = fldnum;
2504*fcf3ce44SJohn Forte 			q->l_next = NULL;
2505*fcf3ce44SJohn Forte #ifdef DEBUG_EXTRA
2506*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2507*fcf3ce44SJohn Forte 			    "read parser: q: word %s value %d\n",
2508*fcf3ce44SJohn Forte 			    q->l_word, q->l_value);
2509*fcf3ce44SJohn Forte #endif
2510*fcf3ce44SJohn Forte 			fldnum++;
2511*fcf3ce44SJohn Forte 		}
2512*fcf3ce44SJohn Forte 		if (*part == 'C')
2513*fcf3ce44SJohn Forte 			i++;
2514*fcf3ce44SJohn Forte 	}
2515*fcf3ce44SJohn Forte 
2516*fcf3ce44SJohn Forte 	/* All done, indicate parser table is loaded */
2517*fcf3ce44SJohn Forte 	if (i && (chead_loaded == 0))
2518*fcf3ce44SJohn Forte 		chead_loaded = cfp->cf_fd;
2519*fcf3ce44SJohn Forte 
2520*fcf3ce44SJohn Forte 	/*
2521*fcf3ce44SJohn Forte 	 * before I go and alloc, why am I here?
2522*fcf3ce44SJohn Forte 	 * do I need a bunch of cfglists, or do I just
2523*fcf3ce44SJohn Forte 	 * need to accommodate a just added parser entry
2524*fcf3ce44SJohn Forte 	 * if the latter, we already have a base, just set
2525*fcf3ce44SJohn Forte 	 * i to the index of the cfg which members need allocing
2526*fcf3ce44SJohn Forte 	 */
2527*fcf3ce44SJohn Forte 	if ((cfp->cf_head->h_cfgs == NULL) ||
2528*fcf3ce44SJohn Forte 	    (cfp->cf_head->h_cfgs[n-1].l_entry == NULL)) {
2529*fcf3ce44SJohn Forte 		cfp->cf_head->h_cfgs = (cfglist_t *)calloc(MAX_CFG,
2530*fcf3ce44SJohn Forte 		    sizeof (cfglist_t));
2531*fcf3ce44SJohn Forte 		i = 0;
2532*fcf3ce44SJohn Forte 	}
2533*fcf3ce44SJohn Forte 	else
2534*fcf3ce44SJohn Forte 		i = n;
2535*fcf3ce44SJohn Forte 
2536*fcf3ce44SJohn Forte 	if (cfp->cf_head->h_cfgs) {
2537*fcf3ce44SJohn Forte 
2538*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2539*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "alloced %d cfg lists \n", n + 1);
2540*fcf3ce44SJohn Forte #endif
2541*fcf3ce44SJohn Forte 		for (cfp->cf_head->h_ncfgs = n + 1;
2542*fcf3ce44SJohn Forte 			i < min(cfp->cf_head->h_ncfgs, MAX_CFG); i++) {
2543*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_name = '\0';
2544*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_name =
2545*fcf3ce44SJohn Forte 			    strdup(chead[i].tag.l_word);
2546*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_index = i;
2547*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_entry =
2548*fcf3ce44SJohn Forte 			    calloc(DEFAULT_ENTRY_SIZE, sizeof (char));
2549*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_nentry = 0;
2550*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_esiz =
2551*fcf3ce44SJohn Forte 			    calloc(DEFAULT_NENTRIES, sizeof (int));
2552*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_size = 0;
2553*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_free = DEFAULT_ENTRY_SIZE;
2554*fcf3ce44SJohn Forte 			if ((cfp->cf_head->h_cfgs[i].l_entry == NULL) ||
2555*fcf3ce44SJohn Forte 			    (cfp->cf_head->h_cfgs[i].l_esiz == NULL)) {
2556*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg", "unable to"
2557*fcf3ce44SJohn Forte 				    " allocate cfglist members");
2558*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
2559*fcf3ce44SJohn Forte 			}
2560*fcf3ce44SJohn Forte 		}
2561*fcf3ce44SJohn Forte 	} else {
2562*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "unable to alloc cfglist");
2563*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2564*fcf3ce44SJohn Forte 	}
2565*fcf3ce44SJohn Forte }
2566*fcf3ce44SJohn Forte 
2567*fcf3ce44SJohn Forte /*
2568*fcf3ce44SJohn Forte  * cfg_map_cfglists()
2569*fcf3ce44SJohn Forte  * go through list of list sizes in header
2570*fcf3ce44SJohn Forte  * and create separate lists
2571*fcf3ce44SJohn Forte  */
2572*fcf3ce44SJohn Forte int
2573*fcf3ce44SJohn Forte cfg_map_cfglists(cfp_t *cfp)
2574*fcf3ce44SJohn Forte {
2575*fcf3ce44SJohn Forte 	int i;
2576*fcf3ce44SJohn Forte 	int offset = 0;
2577*fcf3ce44SJohn Forte 	int *ip;
2578*fcf3ce44SJohn Forte 	int list_size = 0;
2579*fcf3ce44SJohn Forte 	int slot_inc;
2580*fcf3ce44SJohn Forte 	char *p;
2581*fcf3ce44SJohn Forte 	cfgheader_t *ch;
2582*fcf3ce44SJohn Forte 
2583*fcf3ce44SJohn Forte 	ch = cfp->cf_head;
2584*fcf3ce44SJohn Forte 	p = ch->h_cparse;
2585*fcf3ce44SJohn Forte 
2586*fcf3ce44SJohn Forte 	/* get the first list size */
2587*fcf3ce44SJohn Forte 	ip = ch->h_sizes;
2588*fcf3ce44SJohn Forte 
2589*fcf3ce44SJohn Forte 	for (i = 0; i < min(ch->h_ncfgs, MAX_CFG); i++) {
2590*fcf3ce44SJohn Forte 		if (ch->h_cfgsizes[i] > 0) {
2591*fcf3ce44SJohn Forte 			if (ch->h_cfgsizes[i] > DEFAULT_ENTRY_SIZE) {
2592*fcf3ce44SJohn Forte 
2593*fcf3ce44SJohn Forte 				ch->h_cfgs[i].l_entry = (char *)
2594*fcf3ce44SJohn Forte 				    realloc(ch->h_cfgs[i].l_entry,
2595*fcf3ce44SJohn Forte 				    ch->h_cfgsizes[i] * sizeof (char));
2596*fcf3ce44SJohn Forte 				/* set free to 0, we'll get more when we add */
2597*fcf3ce44SJohn Forte 				ch->h_cfgs[i].l_free = 0;
2598*fcf3ce44SJohn Forte 
2599*fcf3ce44SJohn Forte 			} else
2600*fcf3ce44SJohn Forte 				ch->h_cfgs[i].l_free -= ch->h_cfgsizes[i];
2601*fcf3ce44SJohn Forte 
2602*fcf3ce44SJohn Forte 			/* get lists and marry up to each cfgs structure */
2603*fcf3ce44SJohn Forte 
2604*fcf3ce44SJohn Forte 
2605*fcf3ce44SJohn Forte 			list_size = *ip;
2606*fcf3ce44SJohn Forte 			ip++;
2607*fcf3ce44SJohn Forte 
2608*fcf3ce44SJohn Forte 			if (list_size > DEFAULT_NENTRIES) {
2609*fcf3ce44SJohn Forte 				/*
2610*fcf3ce44SJohn Forte 				 *  we're gonna need more slots
2611*fcf3ce44SJohn Forte 				 * we want to alloc on DEFAULT_NENTRIES
2612*fcf3ce44SJohn Forte 				 * boundry. ie. always a multiple of it
2613*fcf3ce44SJohn Forte 				 * later on, when we add to the list
2614*fcf3ce44SJohn Forte 				 * we can see if we need to add by mod'ding
2615*fcf3ce44SJohn Forte 				 * l_nentry and DEFAULT_NENTRIES and check for 0
2616*fcf3ce44SJohn Forte 				 */
2617*fcf3ce44SJohn Forte 				slot_inc = DEFAULT_NENTRIES -
2618*fcf3ce44SJohn Forte 				    (list_size % DEFAULT_NENTRIES);
2619*fcf3ce44SJohn Forte 				if (slot_inc == DEFAULT_NENTRIES)
2620*fcf3ce44SJohn Forte 					slot_inc = 0; /* addcfline reallocs */
2621*fcf3ce44SJohn Forte 
2622*fcf3ce44SJohn Forte 				ch->h_cfgs[i].l_esiz = (int *)realloc(
2623*fcf3ce44SJohn Forte 				    ch->h_cfgs[i].l_esiz,
2624*fcf3ce44SJohn Forte 				    (list_size + slot_inc) * sizeof (int));
2625*fcf3ce44SJohn Forte 			}
2626*fcf3ce44SJohn Forte 			memcpy(ch->h_cfgs[i].l_esiz, ip,
2627*fcf3ce44SJohn Forte 			    list_size * sizeof (int));
2628*fcf3ce44SJohn Forte 
2629*fcf3ce44SJohn Forte 			ch->h_cfgs[i].l_nentry = list_size;
2630*fcf3ce44SJohn Forte 
2631*fcf3ce44SJohn Forte 			ip += list_size;
2632*fcf3ce44SJohn Forte 
2633*fcf3ce44SJohn Forte 		} else
2634*fcf3ce44SJohn Forte 
2635*fcf3ce44SJohn Forte 			continue;
2636*fcf3ce44SJohn Forte 
2637*fcf3ce44SJohn Forte 		if (ch->h_cfgs[i].l_entry != NULL) {
2638*fcf3ce44SJohn Forte 			p = ch->h_cparse + offset;
2639*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2640*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "mapping list %d size %d offset %d, addr 0x%x\n",
2641*fcf3ce44SJohn Forte 	    i, ch->h_cfgsizes[i], offset, p);
2642*fcf3ce44SJohn Forte #endif
2643*fcf3ce44SJohn Forte 			memcpy(ch->h_cfgs[i].l_entry,
2644*fcf3ce44SJohn Forte 			    p, ch->h_cfgsizes[i]);
2645*fcf3ce44SJohn Forte 			ch->h_cfgs[i].l_size = ch->h_cfgsizes[i];
2646*fcf3ce44SJohn Forte 			offset += ch->h_cfgsizes[i];
2647*fcf3ce44SJohn Forte 		} else {
2648*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2649*fcf3ce44SJohn Forte 			(void) fprintf(stderr, "NULL l_entry\n");
2650*fcf3ce44SJohn Forte #endif
2651*fcf3ce44SJohn Forte 			return (-1);
2652*fcf3ce44SJohn Forte 		}
2653*fcf3ce44SJohn Forte 	}
2654*fcf3ce44SJohn Forte 
2655*fcf3ce44SJohn Forte 
2656*fcf3ce44SJohn Forte 	return (1);
2657*fcf3ce44SJohn Forte 
2658*fcf3ce44SJohn Forte }
2659*fcf3ce44SJohn Forte 
2660*fcf3ce44SJohn Forte void
2661*fcf3ce44SJohn Forte cfg_replace_lists(cfp_t *cfp)
2662*fcf3ce44SJohn Forte {
2663*fcf3ce44SJohn Forte 	int i;
2664*fcf3ce44SJohn Forte 	int offset = 0;
2665*fcf3ce44SJohn Forte 	int size_offset = 0;
2666*fcf3ce44SJohn Forte 
2667*fcf3ce44SJohn Forte 	int section = 0;
2668*fcf3ce44SJohn Forte 	cfgheader_t *cf;
2669*fcf3ce44SJohn Forte 	cfglist_t	*cfl;
2670*fcf3ce44SJohn Forte 
2671*fcf3ce44SJohn Forte 	cf = cfp->cf_head;
2672*fcf3ce44SJohn Forte 
2673*fcf3ce44SJohn Forte 	if ((cfl = cfp->cf_head->h_cfgs) == NULL)
2674*fcf3ce44SJohn Forte 		return;
2675*fcf3ce44SJohn Forte 
2676*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2677*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_replace_lists\n");
2678*fcf3ce44SJohn Forte #endif
2679*fcf3ce44SJohn Forte 
2680*fcf3ce44SJohn Forte 	if (cf->h_cparse == cf->h_ccopy1)
2681*fcf3ce44SJohn Forte 		section = 1;
2682*fcf3ce44SJohn Forte 
2683*fcf3ce44SJohn Forte 	/*
2684*fcf3ce44SJohn Forte 	 * check to see if we are using copy1 or 2,
2685*fcf3ce44SJohn Forte 	 * grow or shrink the size, fix h_cparse reference
2686*fcf3ce44SJohn Forte 	 * in case realloc gave us a funky new address.
2687*fcf3ce44SJohn Forte 	 * put stuff in it.
2688*fcf3ce44SJohn Forte 	 */
2689*fcf3ce44SJohn Forte 	cf->h_ccopy1 = (char *)
2690*fcf3ce44SJohn Forte 	    realloc(cf->h_ccopy1, cf->h_csize * sizeof (char));
2691*fcf3ce44SJohn Forte 	cf->h_ccopy2 = (char *)
2692*fcf3ce44SJohn Forte 	    realloc(cf->h_ccopy2, cf->h_csize * sizeof (char));
2693*fcf3ce44SJohn Forte 	if (section == 1) {
2694*fcf3ce44SJohn Forte 		/* we used copy1 */
2695*fcf3ce44SJohn Forte 		cf->h_cparse = cf->h_ccopy1;
2696*fcf3ce44SJohn Forte 	} else
2697*fcf3ce44SJohn Forte 		cf->h_cparse = cf->h_ccopy2;
2698*fcf3ce44SJohn Forte 
2699*fcf3ce44SJohn Forte 	/*
2700*fcf3ce44SJohn Forte 	 * just because, we'll zero out h_csize and recalc
2701*fcf3ce44SJohn Forte 	 * after all, this is the number the next guy gets
2702*fcf3ce44SJohn Forte 	 */
2703*fcf3ce44SJohn Forte 	cf->h_csize = cf->h_sizes[0] = 0;
2704*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_CFG; i++) {
2705*fcf3ce44SJohn Forte 		/* only as many lists as chead has */
2706*fcf3ce44SJohn Forte 		if (chead[i].tag.l_word[0] == '\0') {
2707*fcf3ce44SJohn Forte 			break;
2708*fcf3ce44SJohn Forte 		}
2709*fcf3ce44SJohn Forte 		if (cfl[i].l_entry && cfl[i].l_entry[0] != '\0') {
2710*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2711*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2712*fcf3ce44SJohn Forte 			    "copying list %d at %x size %d\n",
2713*fcf3ce44SJohn Forte 			    i, cf->h_cparse + offset,
2714*fcf3ce44SJohn Forte 			    cfl[i].l_size);
2715*fcf3ce44SJohn Forte #endif
2716*fcf3ce44SJohn Forte 			memcpy((cf->h_cparse + offset),
2717*fcf3ce44SJohn Forte 			    cfl[i].l_entry, cfl[i].l_size);
2718*fcf3ce44SJohn Forte 			offset += cfl[i].l_size;
2719*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2720*fcf3ce44SJohn Forte 			(void) fprintf(stderr,
2721*fcf3ce44SJohn Forte 			    "cfl[%d].l_nentry %d cfl[%d].l_esiz[%d] %d"
2722*fcf3ce44SJohn Forte 			    " size offset %d\n",
2723*fcf3ce44SJohn Forte 			    i, cfl[i].l_nentry, i, cfl[i].l_nentry - 1,
2724*fcf3ce44SJohn Forte 			    cfl[i].l_esiz[cfl[i].l_nentry - 1], size_offset);
2725*fcf3ce44SJohn Forte #endif
2726*fcf3ce44SJohn Forte 			/*
2727*fcf3ce44SJohn Forte 			 * first write the number of entries
2728*fcf3ce44SJohn Forte 			 * then copy over the array ie.
2729*fcf3ce44SJohn Forte 			 * a list with 5 elements would be copied
2730*fcf3ce44SJohn Forte 			 * as a 6 element array slot 0 being the
2731*fcf3ce44SJohn Forte 			 * number of elements
2732*fcf3ce44SJohn Forte 			 */
2733*fcf3ce44SJohn Forte 			cf->h_sizes[size_offset++] = cfl[i].l_nentry;
2734*fcf3ce44SJohn Forte 			memcpy((cf->h_sizes + size_offset), cfl[i].l_esiz,
2735*fcf3ce44SJohn Forte 			    cfl[i].l_nentry * sizeof (int));
2736*fcf3ce44SJohn Forte 			size_offset += cfl[i].l_nentry;
2737*fcf3ce44SJohn Forte 			cf->h_sizes[size_offset] = 0;
2738*fcf3ce44SJohn Forte 		}
2739*fcf3ce44SJohn Forte 		cf->h_csize += cfl[i].l_size;
2740*fcf3ce44SJohn Forte 	}
2741*fcf3ce44SJohn Forte }
2742*fcf3ce44SJohn Forte 
2743*fcf3ce44SJohn Forte void
2744*fcf3ce44SJohn Forte cfg_free_cfglist(cfp_t *cfp)
2745*fcf3ce44SJohn Forte {
2746*fcf3ce44SJohn Forte 	int i;
2747*fcf3ce44SJohn Forte 
2748*fcf3ce44SJohn Forte 	if (!cfp->cf_head || !cfp->cf_head->h_cfgs)
2749*fcf3ce44SJohn Forte 		return;
2750*fcf3ce44SJohn Forte 
2751*fcf3ce44SJohn Forte 	for (i = 0; cfp->cf_head && i < MAX_CFG; i++) {
2752*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_cfgs[i].l_entry) {
2753*fcf3ce44SJohn Forte 			free(cfp->cf_head->h_cfgs[i].l_entry);
2754*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_entry = NULL;
2755*fcf3ce44SJohn Forte 		}
2756*fcf3ce44SJohn Forte 
2757*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_cfgs[i].l_name) {
2758*fcf3ce44SJohn Forte 			free(cfp->cf_head->h_cfgs[i].l_name);
2759*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_entry = NULL;
2760*fcf3ce44SJohn Forte 		}
2761*fcf3ce44SJohn Forte 
2762*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_cfgs[i].l_esiz) {
2763*fcf3ce44SJohn Forte 			free(cfp->cf_head->h_cfgs[i].l_esiz);
2764*fcf3ce44SJohn Forte 			cfp->cf_head->h_cfgs[i].l_esiz = NULL;
2765*fcf3ce44SJohn Forte 		}
2766*fcf3ce44SJohn Forte 	}
2767*fcf3ce44SJohn Forte 
2768*fcf3ce44SJohn Forte 	if (cfp->cf_head) {
2769*fcf3ce44SJohn Forte 		free(cfp->cf_head->h_cfgs);
2770*fcf3ce44SJohn Forte 		cfp->cf_head->h_cfgs = NULL;
2771*fcf3ce44SJohn Forte 	}
2772*fcf3ce44SJohn Forte }
2773*fcf3ce44SJohn Forte 
2774*fcf3ce44SJohn Forte void
2775*fcf3ce44SJohn Forte cfg_free_parser_tree()
2776*fcf3ce44SJohn Forte {
2777*fcf3ce44SJohn Forte 	struct lookup *p = NULL;
2778*fcf3ce44SJohn Forte 	struct lookup *q = NULL;
2779*fcf3ce44SJohn Forte 	int i;
2780*fcf3ce44SJohn Forte 
2781*fcf3ce44SJohn Forte 	for (i = 0; i < MAX_CFG; i++) {
2782*fcf3ce44SJohn Forte 		if (chead)
2783*fcf3ce44SJohn Forte 			p = chead[i].fld;
2784*fcf3ce44SJohn Forte 		while (p) {
2785*fcf3ce44SJohn Forte 			q = p->l_next;
2786*fcf3ce44SJohn Forte 			if (p) {
2787*fcf3ce44SJohn Forte 				free(p);
2788*fcf3ce44SJohn Forte 				p = NULL;
2789*fcf3ce44SJohn Forte 			}
2790*fcf3ce44SJohn Forte 			p = q;
2791*fcf3ce44SJohn Forte 		}
2792*fcf3ce44SJohn Forte 	}
2793*fcf3ce44SJohn Forte 	bzero(chead, MAX_CFG * sizeof (struct parser));
2794*fcf3ce44SJohn Forte }
2795*fcf3ce44SJohn Forte 
2796*fcf3ce44SJohn Forte void
2797*fcf3ce44SJohn Forte cfg_close(CFGFILE *cfg)
2798*fcf3ce44SJohn Forte {
2799*fcf3ce44SJohn Forte 	cfp_t *cfp;
2800*fcf3ce44SJohn Forte 
2801*fcf3ce44SJohn Forte 	if (cfg == NULL) {
2802*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
2803*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2804*fcf3ce44SJohn Forte 		return;
2805*fcf3ce44SJohn Forte 	}
2806*fcf3ce44SJohn Forte 
2807*fcf3ce44SJohn Forte 	/* Determine number of files open */
2808*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
2809*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
2810*fcf3ce44SJohn Forte 
2811*fcf3ce44SJohn Forte 		(*cfp->cf_pp->close)(cfp);
2812*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2813*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "freeing cfglists\n");
2814*fcf3ce44SJohn Forte #endif
2815*fcf3ce44SJohn Forte 		cfg_free_cfglist(cfp);
2816*fcf3ce44SJohn Forte 
2817*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2818*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "freeing cfp->cf_mapped\n");
2819*fcf3ce44SJohn Forte #endif
2820*fcf3ce44SJohn Forte 		free(cfp->cf_mapped);
2821*fcf3ce44SJohn Forte 		cfp->cf_mapped = NULL;
2822*fcf3ce44SJohn Forte 
2823*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2824*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
2825*fcf3ce44SJohn Forte 		    "freeing copy1, copy2, h_sizes and cf\n");
2826*fcf3ce44SJohn Forte #endif
2827*fcf3ce44SJohn Forte 		if (cfp->cf_head) {
2828*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_ccopy1) {
2829*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_ccopy1);
2830*fcf3ce44SJohn Forte 				cfp->cf_head->h_ccopy1 = NULL;
2831*fcf3ce44SJohn Forte 			}
2832*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_ccopy2) {
2833*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_ccopy2);
2834*fcf3ce44SJohn Forte 				cfp->cf_head->h_ccopy2 = NULL;
2835*fcf3ce44SJohn Forte 			}
2836*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_sizes1) {
2837*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_sizes1);
2838*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes1 = NULL;
2839*fcf3ce44SJohn Forte 			}
2840*fcf3ce44SJohn Forte 			if (cfp->cf_head->h_sizes2) {
2841*fcf3ce44SJohn Forte 				free(cfp->cf_head->h_sizes2);
2842*fcf3ce44SJohn Forte 				cfp->cf_head->h_sizes2 = NULL;
2843*fcf3ce44SJohn Forte 			}
2844*fcf3ce44SJohn Forte 
2845*fcf3ce44SJohn Forte 		}
2846*fcf3ce44SJohn Forte 		if (cfp->cf_head)
2847*fcf3ce44SJohn Forte 			free(cfp->cf_head);
2848*fcf3ce44SJohn Forte 	}
2849*fcf3ce44SJohn Forte 
2850*fcf3ce44SJohn Forte 	free(cfg);
2851*fcf3ce44SJohn Forte 	cfg = NULL;
2852*fcf3ce44SJohn Forte 	cfg_free_parser_tree();
2853*fcf3ce44SJohn Forte 
2854*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2855*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_close\n");
2856*fcf3ce44SJohn Forte #endif
2857*fcf3ce44SJohn Forte }
2858*fcf3ce44SJohn Forte 
2859*fcf3ce44SJohn Forte 
2860*fcf3ce44SJohn Forte char *
2861*fcf3ce44SJohn Forte cfg_get_resource(CFGFILE *cfg)
2862*fcf3ce44SJohn Forte {
2863*fcf3ce44SJohn Forte 	if (cfg == NULL) {
2864*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
2865*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2866*fcf3ce44SJohn Forte 		return (NULL);
2867*fcf3ce44SJohn Forte 	}
2868*fcf3ce44SJohn Forte 
2869*fcf3ce44SJohn Forte 	return (cfg->cf_node);
2870*fcf3ce44SJohn Forte }
2871*fcf3ce44SJohn Forte 
2872*fcf3ce44SJohn Forte /*
2873*fcf3ce44SJohn Forte  * cfg_resource
2874*fcf3ce44SJohn Forte  * set or clear the cluster node filter for get/put
2875*fcf3ce44SJohn Forte  */
2876*fcf3ce44SJohn Forte 
2877*fcf3ce44SJohn Forte void
2878*fcf3ce44SJohn Forte cfg_resource(CFGFILE *cfg, const char *node)
2879*fcf3ce44SJohn Forte {
2880*fcf3ce44SJohn Forte 	if (cfg == NULL) {
2881*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
2882*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2883*fcf3ce44SJohn Forte 		return;
2884*fcf3ce44SJohn Forte 	}
2885*fcf3ce44SJohn Forte 
2886*fcf3ce44SJohn Forte 	if (cfg->cf_node) {
2887*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2888*fcf3ce44SJohn Forte 		(void) fprintf(stderr,
2889*fcf3ce44SJohn Forte 		    "cfg_resource: changing node from %s to %s\n",
2890*fcf3ce44SJohn Forte 		    cfg->cf_node, (node?node:"NULL"));
2891*fcf3ce44SJohn Forte #endif
2892*fcf3ce44SJohn Forte 		free(cfg->cf_node);
2893*fcf3ce44SJohn Forte 		cfg->cf_node = NULL;
2894*fcf3ce44SJohn Forte 	}
2895*fcf3ce44SJohn Forte 
2896*fcf3ce44SJohn Forte 	/*
2897*fcf3ce44SJohn Forte 	 * just in case someone passes in a non-NULL
2898*fcf3ce44SJohn Forte 	 * node, but has no valid value
2899*fcf3ce44SJohn Forte 	 */
2900*fcf3ce44SJohn Forte 	if ((node) && (node[0] != '\0')) {
2901*fcf3ce44SJohn Forte 		cfg->cf_node = strdup(node);
2902*fcf3ce44SJohn Forte 	}
2903*fcf3ce44SJohn Forte }
2904*fcf3ce44SJohn Forte 
2905*fcf3ce44SJohn Forte /*
2906*fcf3ce44SJohn Forte  * cfg_open
2907*fcf3ce44SJohn Forte  * Open the current configuration file
2908*fcf3ce44SJohn Forte  */
2909*fcf3ce44SJohn Forte CFGFILE *
2910*fcf3ce44SJohn Forte cfg_open(char *name)
2911*fcf3ce44SJohn Forte {
2912*fcf3ce44SJohn Forte 	CFGFILE *cfg;
2913*fcf3ce44SJohn Forte 	cfp_t *cfp;
2914*fcf3ce44SJohn Forte 	int32_t magic;
2915*fcf3ce44SJohn Forte 	long needed;
2916*fcf3ce44SJohn Forte 	int rc;
2917*fcf3ce44SJohn Forte 
2918*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
2919*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_open\n");
2920*fcf3ce44SJohn Forte #endif
2921*fcf3ce44SJohn Forte 
2922*fcf3ce44SJohn Forte 	cfg_severity = 0;
2923*fcf3ce44SJohn Forte 	if ((cfg = (CFGFILE *)calloc(1, sizeof (*cfg))) == NULL) {
2924*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg",
2925*fcf3ce44SJohn Forte 			"cfg_open: malloc failed");
2926*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
2927*fcf3ce44SJohn Forte 		return (NULL);
2928*fcf3ce44SJohn Forte 	}
2929*fcf3ce44SJohn Forte 
2930*fcf3ce44SJohn Forte 	cfp = &cfg->cf[0];
2931*fcf3ce44SJohn Forte 	if ((name) && strlen(name)) {
2932*fcf3ce44SJohn Forte #ifdef DEBUG
2933*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg_open: Using non-standard name\n");
2934*fcf3ce44SJohn Forte #endif
2935*fcf3ce44SJohn Forte 		cfp->cf_name = name;
2936*fcf3ce44SJohn Forte 		cfp->cf_pp = (strstr(cfp->cf_name, "/rdsk/") == NULL)
2937*fcf3ce44SJohn Forte 			? cfg_block_io_provider()
2938*fcf3ce44SJohn Forte 			: cfg_raw_io_provider();
2939*fcf3ce44SJohn Forte 	} else {
2940*fcf3ce44SJohn Forte 		cfp->cf_name = cfg_location(NULL, CFG_LOC_GET_LOCAL, NULL);
2941*fcf3ce44SJohn Forte 		cfp->cf_pp = cfg_block_io_provider();
2942*fcf3ce44SJohn Forte 
2943*fcf3ce44SJohn Forte 		/* Handle cfg_open(""), which is an open from boot tools */
2944*fcf3ce44SJohn Forte 		if (name)
2945*fcf3ce44SJohn Forte 			cl_initialized = 1;
2946*fcf3ce44SJohn Forte 		if (cfg_iscluster() > 0) {
2947*fcf3ce44SJohn Forte 			cfp = &cfg->cf[1];
2948*fcf3ce44SJohn Forte 			cfp->cf_name =
2949*fcf3ce44SJohn Forte 				cfg_location(NULL, CFG_LOC_GET_CLUSTER, NULL);
2950*fcf3ce44SJohn Forte 			if (cfp->cf_name) {
2951*fcf3ce44SJohn Forte 				cfp->cf_pp = cfg_raw_io_provider();
2952*fcf3ce44SJohn Forte 			}
2953*fcf3ce44SJohn Forte 		}
2954*fcf3ce44SJohn Forte 	}
2955*fcf3ce44SJohn Forte 
2956*fcf3ce44SJohn Forte 	/*
2957*fcf3ce44SJohn Forte 	 * Open one or two configuration files
2958*fcf3ce44SJohn Forte 	 */
2959*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp->cf_name && (cfp <= &cfg->cf[1]); cfp++) {
2960*fcf3ce44SJohn Forte 		if ((*cfp->cf_pp->open)(cfp, cfp->cf_name) == NULL) {
2961*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2962*fcf3ce44SJohn Forte 			    "cfg_open: unable to open configuration location");
2963*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2964*fcf3ce44SJohn Forte 			break;
2965*fcf3ce44SJohn Forte 		}
2966*fcf3ce44SJohn Forte 
2967*fcf3ce44SJohn Forte 		/* block device smaller than repository? */
2968*fcf3ce44SJohn Forte 		rc = (*cfp->cf_pp->read)(cfp, &magic, sizeof (magic));
2969*fcf3ce44SJohn Forte 		if (rc < sizeof (magic)) {
2970*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2971*fcf3ce44SJohn Forte 			    "cfg_open: unable to read configuration header");
2972*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2973*fcf3ce44SJohn Forte 			break;
2974*fcf3ce44SJohn Forte 		}
2975*fcf3ce44SJohn Forte 
2976*fcf3ce44SJohn Forte 		if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
2977*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2978*fcf3ce44SJohn Forte 			    "cfg_open: unable to seek configuration header");
2979*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2980*fcf3ce44SJohn Forte 			break;
2981*fcf3ce44SJohn Forte 		}
2982*fcf3ce44SJohn Forte 
2983*fcf3ce44SJohn Forte 		/*
2984*fcf3ce44SJohn Forte 		 * we can't enforce size rules on an old database
2985*fcf3ce44SJohn Forte 		 * so check the magic number before we test for size
2986*fcf3ce44SJohn Forte 		 */
2987*fcf3ce44SJohn Forte 		if (magic == CFG_NEW_MAGIC) {
2988*fcf3ce44SJohn Forte 			needed = FBA_NUM(FBA_SIZE(1) - 1 +
2989*fcf3ce44SJohn Forte 			(sizeof (struct cfgheader) + CFG_CONFIG_SIZE));
2990*fcf3ce44SJohn Forte 		} else {
2991*fcf3ce44SJohn Forte 			needed = 0;
2992*fcf3ce44SJohn Forte 		}
2993*fcf3ce44SJohn Forte 
2994*fcf3ce44SJohn Forte 		if (cfp->cf_size < needed) {
2995*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
2996*fcf3ce44SJohn Forte 			    "cfg_open: configuration file too small");
2997*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
2998*fcf3ce44SJohn Forte 			errno = ENOMEM;
2999*fcf3ce44SJohn Forte 			break;
3000*fcf3ce44SJohn Forte 		}
3001*fcf3ce44SJohn Forte 
3002*fcf3ce44SJohn Forte 		cfp->cf_mapped = (char *)malloc(CFG_DEFAULT_PARSE_SIZE);
3003*fcf3ce44SJohn Forte 		if (cfp->cf_mapped == NULL) {
3004*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg",
3005*fcf3ce44SJohn Forte 				"cfg_open: malloc failed");
3006*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
3007*fcf3ce44SJohn Forte 			break;
3008*fcf3ce44SJohn Forte 		}
3009*fcf3ce44SJohn Forte 
3010*fcf3ce44SJohn Forte 		bzero(cfp->cf_mapped, CFG_DEFAULT_PARSE_SIZE);
3011*fcf3ce44SJohn Forte 		cfp->cf_lock = -1;
3012*fcf3ce44SJohn Forte 	}
3013*fcf3ce44SJohn Forte 
3014*fcf3ce44SJohn Forte 	/* Processing errors, take care of one or more cfp pointers */
3015*fcf3ce44SJohn Forte 	if (cfg_severity && (cfp <= &cfg->cf[1])) {
3016*fcf3ce44SJohn Forte 		cfp = &cfg->cf[0];
3017*fcf3ce44SJohn Forte 		if (cfp->cf_fd)
3018*fcf3ce44SJohn Forte 			(*cfp->cf_pp->close)(cfp);
3019*fcf3ce44SJohn Forte 		cfp = &cfg->cf[1];
3020*fcf3ce44SJohn Forte 		if (cfp->cf_fd)
3021*fcf3ce44SJohn Forte 			(*cfp->cf_pp->close)(cfp);
3022*fcf3ce44SJohn Forte 		free(cfg);
3023*fcf3ce44SJohn Forte 		return (NULL);
3024*fcf3ce44SJohn Forte 	}
3025*fcf3ce44SJohn Forte 
3026*fcf3ce44SJohn Forte 	cfg_lockd = cfg_lockd_init();
3027*fcf3ce44SJohn Forte 
3028*fcf3ce44SJohn Forte 
3029*fcf3ce44SJohn Forte #ifdef DEBUG_CFGLIST
3030*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "cfg_open ok\n");
3031*fcf3ce44SJohn Forte #endif
3032*fcf3ce44SJohn Forte 	return (cfg);
3033*fcf3ce44SJohn Forte }
3034*fcf3ce44SJohn Forte 
3035*fcf3ce44SJohn Forte void
3036*fcf3ce44SJohn Forte cfg_invalidate_hsizes(int fd, const char *loc) {
3037*fcf3ce44SJohn Forte 	int offset;
3038*fcf3ce44SJohn Forte 	int rc = -1;
3039*fcf3ce44SJohn Forte 	int hdrsz;
3040*fcf3ce44SJohn Forte 
3041*fcf3ce44SJohn Forte 	char buf[2 * CFG_DEFAULT_PSIZE];
3042*fcf3ce44SJohn Forte 
3043*fcf3ce44SJohn Forte 	hdrsz = sizeof (cfgheader_t) + 512 -
3044*fcf3ce44SJohn Forte 	    (sizeof (cfgheader_t) % 512);
3045*fcf3ce44SJohn Forte 
3046*fcf3ce44SJohn Forte 	offset = hdrsz + CFG_DEFAULT_PARSE_SIZE +
3047*fcf3ce44SJohn Forte 	    (CFG_DEFAULT_SSIZE * 2);
3048*fcf3ce44SJohn Forte 
3049*fcf3ce44SJohn Forte 	if (cfg_shldskip_vtoc(fd, loc) > 0)
3050*fcf3ce44SJohn Forte 		offset += CFG_VTOC_SKIP;
3051*fcf3ce44SJohn Forte 
3052*fcf3ce44SJohn Forte 	bzero(buf, sizeof (buf));
3053*fcf3ce44SJohn Forte 
3054*fcf3ce44SJohn Forte 	if (lseek(fd, offset, SEEK_SET) > 0)
3055*fcf3ce44SJohn Forte 		rc = write(fd, buf, sizeof (buf));
3056*fcf3ce44SJohn Forte 	if (rc < 0)
3057*fcf3ce44SJohn Forte 		(void) fprintf(stderr, "cfg: invalidate hsizes failed\n");
3058*fcf3ce44SJohn Forte 
3059*fcf3ce44SJohn Forte }
3060*fcf3ce44SJohn Forte 
3061*fcf3ce44SJohn Forte char *
3062*fcf3ce44SJohn Forte cfg_error(int *severity)
3063*fcf3ce44SJohn Forte {
3064*fcf3ce44SJohn Forte 	if (severity != NULL)
3065*fcf3ce44SJohn Forte 		*severity = cfg_severity;
3066*fcf3ce44SJohn Forte 	return (cfg_perror_str ? cfg_perror_str : CFG_EGENERIC);
3067*fcf3ce44SJohn Forte }
3068*fcf3ce44SJohn Forte /*
3069*fcf3ce44SJohn Forte  * cfg_cfg_isempty
3070*fcf3ce44SJohn Forte  */
3071*fcf3ce44SJohn Forte int
3072*fcf3ce44SJohn Forte cfg_cfg_isempty(CFGFILE *cfg)
3073*fcf3ce44SJohn Forte {
3074*fcf3ce44SJohn Forte 	cfp_t *cfp;
3075*fcf3ce44SJohn Forte 
3076*fcf3ce44SJohn Forte 	if (cfg == NULL) {
3077*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
3078*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3079*fcf3ce44SJohn Forte 		return (FALSE);
3080*fcf3ce44SJohn Forte 	}
3081*fcf3ce44SJohn Forte 
3082*fcf3ce44SJohn Forte 	cfp = FP_SUN_CLUSTER(cfg);
3083*fcf3ce44SJohn Forte 	if (cfp->cf_head->h_csize == 0)
3084*fcf3ce44SJohn Forte 		return (TRUE);
3085*fcf3ce44SJohn Forte 	else
3086*fcf3ce44SJohn Forte 		return (FALSE);
3087*fcf3ce44SJohn Forte }
3088*fcf3ce44SJohn Forte 
3089*fcf3ce44SJohn Forte /*
3090*fcf3ce44SJohn Forte  * cfg_get_num_entries
3091*fcf3ce44SJohn Forte  * return the number of entries in a given section of database
3092*fcf3ce44SJohn Forte  * sndr, ii, ndr_ii...
3093*fcf3ce44SJohn Forte  */
3094*fcf3ce44SJohn Forte int
3095*fcf3ce44SJohn Forte cfg_get_num_entries(CFGFILE *cfg, char *section)
3096*fcf3ce44SJohn Forte {
3097*fcf3ce44SJohn Forte 	int count = 0;
3098*fcf3ce44SJohn Forte 	int table_offset;
3099*fcf3ce44SJohn Forte 	cfp_t *cfp;
3100*fcf3ce44SJohn Forte 
3101*fcf3ce44SJohn Forte 	if (cfg == NULL) {
3102*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
3103*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3104*fcf3ce44SJohn Forte 		return (-1);
3105*fcf3ce44SJohn Forte 	}
3106*fcf3ce44SJohn Forte 
3107*fcf3ce44SJohn Forte 	if ((table_offset = cfg_get_parser_offset(section)) < 0) {
3108*fcf3ce44SJohn Forte 		errno = ESRCH;
3109*fcf3ce44SJohn Forte 		return (-1);
3110*fcf3ce44SJohn Forte 	}
3111*fcf3ce44SJohn Forte 
3112*fcf3ce44SJohn Forte 	/* Determine number of files open */
3113*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp->cf_fd && (cfp <= &cfg->cf[1]); cfp++)
3114*fcf3ce44SJohn Forte 		count += cfp->cf_head->h_cfgs[table_offset].l_nentry;
3115*fcf3ce44SJohn Forte 
3116*fcf3ce44SJohn Forte 	return (count);
3117*fcf3ce44SJohn Forte }
3118*fcf3ce44SJohn Forte 
3119*fcf3ce44SJohn Forte /*
3120*fcf3ce44SJohn Forte  * cfg_get_section
3121*fcf3ce44SJohn Forte  * all etries in a config file section is placed in
3122*fcf3ce44SJohn Forte  * buf, allocation is done inside
3123*fcf3ce44SJohn Forte  * freeing buf is responisbility of the caller
3124*fcf3ce44SJohn Forte  * number of entries in section is returned
3125*fcf3ce44SJohn Forte  * -1 on failure, errno is set
3126*fcf3ce44SJohn Forte  */
3127*fcf3ce44SJohn Forte int
3128*fcf3ce44SJohn Forte cfg_get_section(CFGFILE *cfg, char ***list, const char *section)
3129*fcf3ce44SJohn Forte {
3130*fcf3ce44SJohn Forte 	int table_offset;
3131*fcf3ce44SJohn Forte 	int i, count;
3132*fcf3ce44SJohn Forte 	cfglist_t *cfl;
3133*fcf3ce44SJohn Forte 	char *p = NULL;
3134*fcf3ce44SJohn Forte 	char **buf;
3135*fcf3ce44SJohn Forte 	cfp_t *cfp;
3136*fcf3ce44SJohn Forte 
3137*fcf3ce44SJohn Forte 	if (cfg == NULL) {
3138*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
3139*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3140*fcf3ce44SJohn Forte 		return (FALSE);
3141*fcf3ce44SJohn Forte 	}
3142*fcf3ce44SJohn Forte 
3143*fcf3ce44SJohn Forte 	if ((table_offset = cfg_get_parser_offset(section)) < 0) {
3144*fcf3ce44SJohn Forte 		errno = ESRCH;
3145*fcf3ce44SJohn Forte 		return (-1);
3146*fcf3ce44SJohn Forte 	}
3147*fcf3ce44SJohn Forte 
3148*fcf3ce44SJohn Forte 	/* Determine number of files open */
3149*fcf3ce44SJohn Forte 	count = 0;
3150*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
3151*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
3152*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
3153*fcf3ce44SJohn Forte 			if (!cfg_read(cfp)) {
3154*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
3155*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
3156*fcf3ce44SJohn Forte 				return (-1);
3157*fcf3ce44SJohn Forte 			}
3158*fcf3ce44SJohn Forte 		}
3159*fcf3ce44SJohn Forte 
3160*fcf3ce44SJohn Forte 		cfl = &cfp->cf_head->h_cfgs[table_offset];
3161*fcf3ce44SJohn Forte 		if (cfl->l_nentry == 0) /* empty list */
3162*fcf3ce44SJohn Forte 			continue;
3163*fcf3ce44SJohn Forte 
3164*fcf3ce44SJohn Forte 		if (count == 0)
3165*fcf3ce44SJohn Forte 			buf = (char **)malloc(cfl->l_nentry * sizeof (char *));
3166*fcf3ce44SJohn Forte 		else
3167*fcf3ce44SJohn Forte 			buf = (char **)realloc(buf, (cfl->l_nentry + count) *
3168*fcf3ce44SJohn Forte 						sizeof (char *));
3169*fcf3ce44SJohn Forte 		if (buf == NULL) {
3170*fcf3ce44SJohn Forte 			errno = ENOMEM;
3171*fcf3ce44SJohn Forte 			return (-1);
3172*fcf3ce44SJohn Forte 		} else {
3173*fcf3ce44SJohn Forte 			bzero(&buf[count], cfl->l_nentry * sizeof (char *));
3174*fcf3ce44SJohn Forte 		}
3175*fcf3ce44SJohn Forte 
3176*fcf3ce44SJohn Forte 		p = cfl->l_entry;
3177*fcf3ce44SJohn Forte 		for (i = 0; i < cfl->l_nentry; i++) {
3178*fcf3ce44SJohn Forte 			if ((buf[i + count] = strdup(p)) == NULL) {
3179*fcf3ce44SJohn Forte 				errno = ENOMEM;
3180*fcf3ce44SJohn Forte 				return (-1);
3181*fcf3ce44SJohn Forte 			}
3182*fcf3ce44SJohn Forte 			p += cfl->l_esiz[i];
3183*fcf3ce44SJohn Forte 		}
3184*fcf3ce44SJohn Forte 		count +=  cfl->l_nentry;
3185*fcf3ce44SJohn Forte 	}
3186*fcf3ce44SJohn Forte 
3187*fcf3ce44SJohn Forte 	*list = buf;
3188*fcf3ce44SJohn Forte 	return (count);
3189*fcf3ce44SJohn Forte }
3190*fcf3ce44SJohn Forte 
3191*fcf3ce44SJohn Forte /*
3192*fcf3ce44SJohn Forte  * cluster upgrade helper functions. These support old database operations
3193*fcf3ce44SJohn Forte  * while upgrading nodes on a cluster.
3194*fcf3ce44SJohn Forte  */
3195*fcf3ce44SJohn Forte 
3196*fcf3ce44SJohn Forte /*
3197*fcf3ce44SJohn Forte  * returns the list of configured tags
3198*fcf3ce44SJohn Forte  * return -1 on error, else the number
3199*fcf3ce44SJohn Forte  * of tags returned in taglist
3200*fcf3ce44SJohn Forte  * caller frees
3201*fcf3ce44SJohn Forte  */
3202*fcf3ce44SJohn Forte int
3203*fcf3ce44SJohn Forte cfg_get_tags(CFGFILE *cfg, char ***taglist)
3204*fcf3ce44SJohn Forte {
3205*fcf3ce44SJohn Forte 	char **list;
3206*fcf3ce44SJohn Forte 	int i = 0;
3207*fcf3ce44SJohn Forte 
3208*fcf3ce44SJohn Forte 	if (cfg == NULL) {
3209*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
3210*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3211*fcf3ce44SJohn Forte 		return (-1);
3212*fcf3ce44SJohn Forte 	}
3213*fcf3ce44SJohn Forte 
3214*fcf3ce44SJohn Forte 	if (!cfg_rdlock(cfg)) {
3215*fcf3ce44SJohn Forte 		return (-1);
3216*fcf3ce44SJohn Forte 	}
3217*fcf3ce44SJohn Forte 	list = calloc(1, MAX_CFG * sizeof (char *));
3218*fcf3ce44SJohn Forte 	if (list == NULL) {
3219*fcf3ce44SJohn Forte 		errno = ENOMEM;
3220*fcf3ce44SJohn Forte 		return (-1);
3221*fcf3ce44SJohn Forte 	}
3222*fcf3ce44SJohn Forte 
3223*fcf3ce44SJohn Forte 	while ((i < MAX_CFG) && (chead[i].tag.l_word[0] != '\0')) {
3224*fcf3ce44SJohn Forte 		list[i] = strdup(chead[i].tag.l_word);
3225*fcf3ce44SJohn Forte 		if (list[i] == NULL) {
3226*fcf3ce44SJohn Forte 			for (/* CSTYLE */; i >= 0; i--) {
3227*fcf3ce44SJohn Forte 				if (list[i])
3228*fcf3ce44SJohn Forte 					free(list[i]);
3229*fcf3ce44SJohn Forte 			}
3230*fcf3ce44SJohn Forte 			free(list);
3231*fcf3ce44SJohn Forte 			errno = ENOMEM;
3232*fcf3ce44SJohn Forte 			return (-1);
3233*fcf3ce44SJohn Forte 		}
3234*fcf3ce44SJohn Forte 		i++;
3235*fcf3ce44SJohn Forte 	}
3236*fcf3ce44SJohn Forte 	*taglist = list;
3237*fcf3ce44SJohn Forte 	return (i);
3238*fcf3ce44SJohn Forte 
3239*fcf3ce44SJohn Forte }
3240*fcf3ce44SJohn Forte 
3241*fcf3ce44SJohn Forte /*
3242*fcf3ce44SJohn Forte  * is this a database?
3243*fcf3ce44SJohn Forte  * check the header for the magic number
3244*fcf3ce44SJohn Forte  * 0 no match 1 match, -1 on error
3245*fcf3ce44SJohn Forte  */
3246*fcf3ce44SJohn Forte int
3247*fcf3ce44SJohn Forte cfg_is_cfg(CFGFILE *cfg)
3248*fcf3ce44SJohn Forte {
3249*fcf3ce44SJohn Forte 	int32_t magic;
3250*fcf3ce44SJohn Forte 	int rc;
3251*fcf3ce44SJohn Forte 	cfp_t *cfp = FP_SUN_CLUSTER(cfg);
3252*fcf3ce44SJohn Forte 
3253*fcf3ce44SJohn Forte 	rc = (cfp->cf_pp->read)(cfp, &magic, sizeof (magic));
3254*fcf3ce44SJohn Forte 	if (rc < sizeof (magic)) {
3255*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "Fail to read configuration");
3256*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3257*fcf3ce44SJohn Forte 		return (-1);
3258*fcf3ce44SJohn Forte 	}
3259*fcf3ce44SJohn Forte 
3260*fcf3ce44SJohn Forte 	if (magic == CFG_NEW_MAGIC)
3261*fcf3ce44SJohn Forte 		return (1);
3262*fcf3ce44SJohn Forte 
3263*fcf3ce44SJohn Forte 	cfg_perror_str = dgettext("cfg",
3264*fcf3ce44SJohn Forte 		"configuration not initialized, bad magic");
3265*fcf3ce44SJohn Forte 	cfg_severity = CFG_EFATAL;
3266*fcf3ce44SJohn Forte 
3267*fcf3ce44SJohn Forte 	return (0);
3268*fcf3ce44SJohn Forte }
3269*fcf3ce44SJohn Forte 
3270*fcf3ce44SJohn Forte int
3271*fcf3ce44SJohn Forte compare(const void* a, const void *b)
3272*fcf3ce44SJohn Forte {
3273*fcf3ce44SJohn Forte 	char *p;
3274*fcf3ce44SJohn Forte 	char *pbuf;
3275*fcf3ce44SJohn Forte 	char *q;
3276*fcf3ce44SJohn Forte 	char *qbuf;
3277*fcf3ce44SJohn Forte 	int needed;
3278*fcf3ce44SJohn Forte 	int cmp;
3279*fcf3ce44SJohn Forte 	int pos;
3280*fcf3ce44SJohn Forte 
3281*fcf3ce44SJohn Forte 	pbuf = strdup(a);
3282*fcf3ce44SJohn Forte 	qbuf = strdup(b);
3283*fcf3ce44SJohn Forte 
3284*fcf3ce44SJohn Forte 	if (!qbuf || !pbuf)
3285*fcf3ce44SJohn Forte 		return (0);
3286*fcf3ce44SJohn Forte 
3287*fcf3ce44SJohn Forte 	pos = 1;
3288*fcf3ce44SJohn Forte 	needed = sortby.offset;
3289*fcf3ce44SJohn Forte 
3290*fcf3ce44SJohn Forte 	p = strtok(pbuf, " ");
3291*fcf3ce44SJohn Forte 	while (p) {
3292*fcf3ce44SJohn Forte 		if (needed == pos) {
3293*fcf3ce44SJohn Forte 			break;
3294*fcf3ce44SJohn Forte 		}
3295*fcf3ce44SJohn Forte 		p = strtok(NULL, " ");
3296*fcf3ce44SJohn Forte 		if (!p)
3297*fcf3ce44SJohn Forte 			break;
3298*fcf3ce44SJohn Forte 		pos++;
3299*fcf3ce44SJohn Forte 	}
3300*fcf3ce44SJohn Forte 
3301*fcf3ce44SJohn Forte 	pos = 1;
3302*fcf3ce44SJohn Forte 	q = strtok(qbuf, " ");
3303*fcf3ce44SJohn Forte 	while (q) {
3304*fcf3ce44SJohn Forte 		if (needed == pos) {
3305*fcf3ce44SJohn Forte 			break;
3306*fcf3ce44SJohn Forte 		}
3307*fcf3ce44SJohn Forte 		q = strtok(NULL, " ");
3308*fcf3ce44SJohn Forte 		if (!q)
3309*fcf3ce44SJohn Forte 			break;
3310*fcf3ce44SJohn Forte 		pos++;
3311*fcf3ce44SJohn Forte 	}
3312*fcf3ce44SJohn Forte 	if (!p || !q) {
3313*fcf3ce44SJohn Forte 		sortby.comperror++;
3314*fcf3ce44SJohn Forte 		free(pbuf);
3315*fcf3ce44SJohn Forte 		free(qbuf);
3316*fcf3ce44SJohn Forte 		return (0);
3317*fcf3ce44SJohn Forte 	}
3318*fcf3ce44SJohn Forte 	cmp = strcmp(p, q);
3319*fcf3ce44SJohn Forte 	free(pbuf);
3320*fcf3ce44SJohn Forte 	free(qbuf);
3321*fcf3ce44SJohn Forte 	return (cmp);
3322*fcf3ce44SJohn Forte 
3323*fcf3ce44SJohn Forte 
3324*fcf3ce44SJohn Forte }
3325*fcf3ce44SJohn Forte /*
3326*fcf3ce44SJohn Forte  * cfg_get_srtdsec
3327*fcf3ce44SJohn Forte  * returns the section, sorted by supplied field
3328*fcf3ce44SJohn Forte  * caller frees mem
3329*fcf3ce44SJohn Forte  */
3330*fcf3ce44SJohn Forte int
3331*fcf3ce44SJohn Forte cfg_get_srtdsec(CFGFILE *cfg, char ***list, const char *section,
3332*fcf3ce44SJohn Forte 	const char *field)
3333*fcf3ce44SJohn Forte {
3334*fcf3ce44SJohn Forte 	cfglist_t *cfl;
3335*fcf3ce44SJohn Forte 	cfp_t *cfp;
3336*fcf3ce44SJohn Forte 	char **buf;
3337*fcf3ce44SJohn Forte 	char *tmplst;
3338*fcf3ce44SJohn Forte 	char *p, *q;
3339*fcf3ce44SJohn Forte 	int table_offset;
3340*fcf3ce44SJohn Forte 	int count, i;
3341*fcf3ce44SJohn Forte 
3342*fcf3ce44SJohn Forte 	if (cfg == NULL) {
3343*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_EINVAL);
3344*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3345*fcf3ce44SJohn Forte 		return (FALSE);
3346*fcf3ce44SJohn Forte 	}
3347*fcf3ce44SJohn Forte 
3348*fcf3ce44SJohn Forte 	if ((table_offset = cfg_get_parser_offset(section)) < 0) {
3349*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
3350*fcf3ce44SJohn Forte 		errno = ESRCH;
3351*fcf3ce44SJohn Forte 		return (-1);
3352*fcf3ce44SJohn Forte 	}
3353*fcf3ce44SJohn Forte 
3354*fcf3ce44SJohn Forte 	/*
3355*fcf3ce44SJohn Forte 	 * do essentially what get_section does,
3356*fcf3ce44SJohn Forte 	 * except stick entries in a static size
3357*fcf3ce44SJohn Forte 	 * buf to make things easier to qsort
3358*fcf3ce44SJohn Forte 	 */
3359*fcf3ce44SJohn Forte 	count = 0;
3360*fcf3ce44SJohn Forte 	for (cfp = &cfg->cf[0]; cfp <= &cfg->cf[1]; cfp++) {
3361*fcf3ce44SJohn Forte 		if (!cfp->cf_fd) continue;
3362*fcf3ce44SJohn Forte 		if (cfp->cf_head->h_state & CFG_HDR_INVALID) {
3363*fcf3ce44SJohn Forte 			if (!cfg_read(cfp)) {
3364*fcf3ce44SJohn Forte 				cfg_perror_str = dgettext("cfg", CFG_RDFAILED);
3365*fcf3ce44SJohn Forte 				cfg_severity = CFG_EFATAL;
3366*fcf3ce44SJohn Forte 				return (-1);
3367*fcf3ce44SJohn Forte 			}
3368*fcf3ce44SJohn Forte 		}
3369*fcf3ce44SJohn Forte 
3370*fcf3ce44SJohn Forte 		cfl = &cfp->cf_head->h_cfgs[table_offset];
3371*fcf3ce44SJohn Forte 		if (cfl->l_nentry == 0) /* empty list */
3372*fcf3ce44SJohn Forte 			continue;
3373*fcf3ce44SJohn Forte 
3374*fcf3ce44SJohn Forte 		if (count == 0)
3375*fcf3ce44SJohn Forte 			buf = (char **)malloc(cfl->l_nentry * sizeof (char *));
3376*fcf3ce44SJohn Forte 		else
3377*fcf3ce44SJohn Forte 			buf = (char **)realloc(buf, (cfl->l_nentry + count) *
3378*fcf3ce44SJohn Forte 						sizeof (char *));
3379*fcf3ce44SJohn Forte 		if (buf == NULL) {
3380*fcf3ce44SJohn Forte 			errno = ENOMEM;
3381*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", "cfg_get_srtdsec: "
3382*fcf3ce44SJohn Forte 			    "malloc failed");
3383*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
3384*fcf3ce44SJohn Forte 			return (-1);
3385*fcf3ce44SJohn Forte 		} else {
3386*fcf3ce44SJohn Forte 			bzero(&buf[count], cfl->l_nentry * sizeof (char *));
3387*fcf3ce44SJohn Forte 		}
3388*fcf3ce44SJohn Forte 
3389*fcf3ce44SJohn Forte 		/*
3390*fcf3ce44SJohn Forte 		 * allocate each line
3391*fcf3ce44SJohn Forte 		 */
3392*fcf3ce44SJohn Forte 		for (i = count; i < cfl->l_nentry + count; i++) {
3393*fcf3ce44SJohn Forte 			buf[i] = calloc(1, CFG_MAX_BUF);
3394*fcf3ce44SJohn Forte 			if (buf[i] == NULL) {
3395*fcf3ce44SJohn Forte 				free(buf);
3396*fcf3ce44SJohn Forte 				errno = ENOMEM;
3397*fcf3ce44SJohn Forte 				return (-1);
3398*fcf3ce44SJohn Forte 			}
3399*fcf3ce44SJohn Forte 		}
3400*fcf3ce44SJohn Forte 
3401*fcf3ce44SJohn Forte 		if (count == 0)
3402*fcf3ce44SJohn Forte 			tmplst = (char *)malloc(cfl->l_nentry * CFG_MAX_BUF);
3403*fcf3ce44SJohn Forte 		else
3404*fcf3ce44SJohn Forte 			tmplst = (char *)realloc(tmplst,
3405*fcf3ce44SJohn Forte 					(cfl->l_nentry + count) * CFG_MAX_BUF);
3406*fcf3ce44SJohn Forte 		if (tmplst == NULL) {
3407*fcf3ce44SJohn Forte 			cfg_perror_str = dgettext("cfg", "cfg_get_srtdsec: "
3408*fcf3ce44SJohn Forte 			    "malloc failed");
3409*fcf3ce44SJohn Forte 			cfg_severity = CFG_EFATAL;
3410*fcf3ce44SJohn Forte 			free(buf);
3411*fcf3ce44SJohn Forte 			return (-1);
3412*fcf3ce44SJohn Forte 		} else {
3413*fcf3ce44SJohn Forte 			bzero(&tmplst[count], cfl->l_nentry * CFG_MAX_BUF);
3414*fcf3ce44SJohn Forte 		}
3415*fcf3ce44SJohn Forte 
3416*fcf3ce44SJohn Forte 		/*
3417*fcf3ce44SJohn Forte 		 * put the section in tmplst and sort
3418*fcf3ce44SJohn Forte 		 */
3419*fcf3ce44SJohn Forte 		p = &tmplst[count];
3420*fcf3ce44SJohn Forte 		q = cfl->l_entry;
3421*fcf3ce44SJohn Forte 		for (i = 0; i < cfl->l_nentry; i++) {
3422*fcf3ce44SJohn Forte 			bcopy(q, p, cfl->l_esiz[i]);
3423*fcf3ce44SJohn Forte 			p += CFG_MAX_BUF;
3424*fcf3ce44SJohn Forte 			q += cfl->l_esiz[i];
3425*fcf3ce44SJohn Forte 		}
3426*fcf3ce44SJohn Forte 		count += cfl->l_nentry;
3427*fcf3ce44SJohn Forte 	}
3428*fcf3ce44SJohn Forte 
3429*fcf3ce44SJohn Forte 	bzero(sortby.section, CFG_MAX_KEY);
3430*fcf3ce44SJohn Forte 	bzero(sortby.field, CFG_MAX_KEY);
3431*fcf3ce44SJohn Forte 
3432*fcf3ce44SJohn Forte 	strcpy(sortby.section, section);
3433*fcf3ce44SJohn Forte 	strcpy(sortby.field, field);
3434*fcf3ce44SJohn Forte 	sortby.comperror = 0;
3435*fcf3ce44SJohn Forte 	sortby.offset = cfg_get_item(&chead[0], section, field);
3436*fcf3ce44SJohn Forte 
3437*fcf3ce44SJohn Forte 	qsort(tmplst, count, CFG_MAX_BUF, compare);
3438*fcf3ce44SJohn Forte 
3439*fcf3ce44SJohn Forte 	if (sortby.comperror) {
3440*fcf3ce44SJohn Forte 		sortby.comperror = 0;
3441*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "cfg_get_srtdsec: "
3442*fcf3ce44SJohn Forte 		    "comparison error");
3443*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
3444*fcf3ce44SJohn Forte 		cfg_free_section(&buf, cfl->l_nentry);
3445*fcf3ce44SJohn Forte 		free(tmplst);
3446*fcf3ce44SJohn Forte 		*list = NULL;
3447*fcf3ce44SJohn Forte 		return (-1);
3448*fcf3ce44SJohn Forte 	}
3449*fcf3ce44SJohn Forte 
3450*fcf3ce44SJohn Forte 	p = tmplst;
3451*fcf3ce44SJohn Forte 	for (i = 0; i < count; i++) {
3452*fcf3ce44SJohn Forte 		bcopy(p, buf[i], CFG_MAX_BUF);
3453*fcf3ce44SJohn Forte 		p +=  CFG_MAX_BUF;
3454*fcf3ce44SJohn Forte 	}
3455*fcf3ce44SJohn Forte 
3456*fcf3ce44SJohn Forte 	free(tmplst);
3457*fcf3ce44SJohn Forte 	*list = buf;
3458*fcf3ce44SJohn Forte 	return (count);
3459*fcf3ce44SJohn Forte }
3460*fcf3ce44SJohn Forte 
3461*fcf3ce44SJohn Forte /*
3462*fcf3ce44SJohn Forte  * free an array alloc'd by get_*section
3463*fcf3ce44SJohn Forte  * or some other array of size size
3464*fcf3ce44SJohn Forte  */
3465*fcf3ce44SJohn Forte 
3466*fcf3ce44SJohn Forte void
3467*fcf3ce44SJohn Forte cfg_free_section(char ***section, int size)
3468*fcf3ce44SJohn Forte {
3469*fcf3ce44SJohn Forte 	int i;
3470*fcf3ce44SJohn Forte 	char **secpp = *section;
3471*fcf3ce44SJohn Forte 
3472*fcf3ce44SJohn Forte 	for (i = 0; i < size; i++) {
3473*fcf3ce44SJohn Forte 		if (secpp[i]) {
3474*fcf3ce44SJohn Forte 			free(secpp[i]);
3475*fcf3ce44SJohn Forte 			secpp[i] = NULL;
3476*fcf3ce44SJohn Forte 		}
3477*fcf3ce44SJohn Forte 	}
3478*fcf3ce44SJohn Forte 	if (secpp) {
3479*fcf3ce44SJohn Forte 		free(secpp);
3480*fcf3ce44SJohn Forte 		secpp = NULL;
3481*fcf3ce44SJohn Forte 	}
3482*fcf3ce44SJohn Forte 	section = NULL;
3483*fcf3ce44SJohn Forte }
3484*fcf3ce44SJohn Forte 
3485*fcf3ce44SJohn Forte 
3486*fcf3ce44SJohn Forte int
3487*fcf3ce44SJohn Forte cfg_shldskip_vtoc(int fd, const char *loc)
3488*fcf3ce44SJohn Forte {
3489*fcf3ce44SJohn Forte 	struct vtoc vtoc;
3490*fcf3ce44SJohn Forte 	struct stat sb;
3491*fcf3ce44SJohn Forte 	int slice;
3492*fcf3ce44SJohn Forte 	int rfd;
3493*fcf3ce44SJohn Forte 	char char_name[PATH_MAX];
3494*fcf3ce44SJohn Forte 	char *p;
3495*fcf3ce44SJohn Forte 
3496*fcf3ce44SJohn Forte 	if (fstat(fd, &sb) == -1) {
3497*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "unable to stat config");
3498*fcf3ce44SJohn Forte 		cfg_severity = CFG_EFATAL;
3499*fcf3ce44SJohn Forte 		return (-1);
3500*fcf3ce44SJohn Forte 	}
3501*fcf3ce44SJohn Forte 	if (S_ISREG(sb.st_mode))
3502*fcf3ce44SJohn Forte 		return (0);
3503*fcf3ce44SJohn Forte 
3504*fcf3ce44SJohn Forte 	if (S_ISCHR(sb.st_mode)) {
3505*fcf3ce44SJohn Forte 		if ((slice = read_vtoc(fd, &vtoc)) < 0)
3506*fcf3ce44SJohn Forte 			return (-1);
3507*fcf3ce44SJohn Forte 
3508*fcf3ce44SJohn Forte 		if (vtoc.v_part[slice].p_start < CFG_VTOC_SIZE)
3509*fcf3ce44SJohn Forte 			return (1);
3510*fcf3ce44SJohn Forte 		else
3511*fcf3ce44SJohn Forte 			return (0);
3512*fcf3ce44SJohn Forte 	}
3513*fcf3ce44SJohn Forte 
3514*fcf3ce44SJohn Forte 	if (S_ISBLK(sb.st_mode)) {
3515*fcf3ce44SJohn Forte 		p = strstr(loc, "/dsk/");
3516*fcf3ce44SJohn Forte 		if (p == NULL)
3517*fcf3ce44SJohn Forte 			return (-1);
3518*fcf3ce44SJohn Forte 		strcpy(char_name, loc);
3519*fcf3ce44SJohn Forte 		char_name[strlen(loc) - strlen(p)] = 0;
3520*fcf3ce44SJohn Forte 		strcat(char_name, "/rdsk/");
3521*fcf3ce44SJohn Forte 		strcat(char_name, p + 5);
3522*fcf3ce44SJohn Forte 
3523*fcf3ce44SJohn Forte 		if ((rfd = open(char_name, O_RDONLY)) < 0) {
3524*fcf3ce44SJohn Forte 			return (-1);
3525*fcf3ce44SJohn Forte 		}
3526*fcf3ce44SJohn Forte 		if ((slice = read_vtoc(rfd, &vtoc)) < 0) {
3527*fcf3ce44SJohn Forte 			close(rfd);
3528*fcf3ce44SJohn Forte 			return (-1);
3529*fcf3ce44SJohn Forte 		}
3530*fcf3ce44SJohn Forte 		close(rfd);
3531*fcf3ce44SJohn Forte 		if (vtoc.v_part[slice].p_start < CFG_VTOC_SIZE)
3532*fcf3ce44SJohn Forte 			return (1);
3533*fcf3ce44SJohn Forte 		else
3534*fcf3ce44SJohn Forte 			return (0);
3535*fcf3ce44SJohn Forte 	}
3536*fcf3ce44SJohn Forte 
3537*fcf3ce44SJohn Forte 	return (-1);
3538*fcf3ce44SJohn Forte }
3539*fcf3ce44SJohn Forte 
3540*fcf3ce44SJohn Forte /*
3541*fcf3ce44SJohn Forte  * comapares incore header with one on disk
3542*fcf3ce44SJohn Forte  * returns 0 if equal, 1 if not,  -1 error
3543*fcf3ce44SJohn Forte  */
3544*fcf3ce44SJohn Forte int
3545*fcf3ce44SJohn Forte cfg_hdrcmp(cfp_t *cfp)
3546*fcf3ce44SJohn Forte {
3547*fcf3ce44SJohn Forte 	cfgheader_t *dskhdr, *memhdr;
3548*fcf3ce44SJohn Forte 	int rc;
3549*fcf3ce44SJohn Forte 
3550*fcf3ce44SJohn Forte 	if ((dskhdr = calloc(1, sizeof (*dskhdr))) == NULL) {
3551*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "cfg_hdrcmp: No memory");
3552*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
3553*fcf3ce44SJohn Forte 	}
3554*fcf3ce44SJohn Forte 
3555*fcf3ce44SJohn Forte 	if ((*cfp->cf_pp->seek)(cfp, 0, SEEK_SET) < 0) {
3556*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "cfg_hdrcmp: seek failed");
3557*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
3558*fcf3ce44SJohn Forte 		free(dskhdr);
3559*fcf3ce44SJohn Forte 		return (-1);
3560*fcf3ce44SJohn Forte 	}
3561*fcf3ce44SJohn Forte 
3562*fcf3ce44SJohn Forte 	rc = (*cfp->cf_pp->read)(cfp, (char *)dskhdr, sizeof (*dskhdr));
3563*fcf3ce44SJohn Forte 	if (rc < 0) {
3564*fcf3ce44SJohn Forte 		cfg_perror_str = dgettext("cfg", "cfg_hdrcmp: read failed");
3565*fcf3ce44SJohn Forte 		cfg_severity = CFG_ENONFATAL;
3566*fcf3ce44SJohn Forte 		free(dskhdr);
3567*fcf3ce44SJohn Forte 		return (-1);
3568*fcf3ce44SJohn Forte 	}
3569*fcf3ce44SJohn Forte 
3570*fcf3ce44SJohn Forte 	memhdr = cfp->cf_head;
3571*fcf3ce44SJohn Forte 
3572*fcf3ce44SJohn Forte 	if ((memhdr->h_seq1 == dskhdr->h_seq1) &&
3573*fcf3ce44SJohn Forte 	    (memhdr->h_seq2 == dskhdr->h_seq2))
3574*fcf3ce44SJohn Forte 		rc = 0;
3575*fcf3ce44SJohn Forte 	else
3576*fcf3ce44SJohn Forte 		rc = 1;
3577*fcf3ce44SJohn Forte 
3578*fcf3ce44SJohn Forte 
3579*fcf3ce44SJohn Forte 	free(dskhdr);
3580*fcf3ce44SJohn Forte 	return (rc);
3581*fcf3ce44SJohn Forte }
3582