1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * This module implements the routine to parse the configuration file.
31*7c478bd9Sstevel@tonic-gate  */
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <stdio.h>
35*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
38*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
39*7c478bd9Sstevel@tonic-gate #include <string.h>
40*7c478bd9Sstevel@tonic-gate #include <ctype.h>
41*7c478bd9Sstevel@tonic-gate #include <alloca.h>
42*7c478bd9Sstevel@tonic-gate #include <limits.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
46*7c478bd9Sstevel@tonic-gate #include <libintl.h>
47*7c478bd9Sstevel@tonic-gate #include <syslog.h>
48*7c478bd9Sstevel@tonic-gate #include <locale.h>
49*7c478bd9Sstevel@tonic-gate #include <picl.h>
50*7c478bd9Sstevel@tonic-gate #include <picltree.h>
51*7c478bd9Sstevel@tonic-gate #include "picld_pluginutil.h"
52*7c478bd9Sstevel@tonic-gate #include "picld_pluginutil_impl.h"
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /* error codes returned from syntax checking */
55*7c478bd9Sstevel@tonic-gate #define	EC_SYNTAX_OK		0
56*7c478bd9Sstevel@tonic-gate #define	EC_INSUFFICIENT_TOKEN	1
57*7c478bd9Sstevel@tonic-gate #define	EC_SYNTAX_ERR		2
58*7c478bd9Sstevel@tonic-gate #define	EC_UNSUPPORTED		3
59*7c478bd9Sstevel@tonic-gate #define	EC_PATH_ERR		4
60*7c478bd9Sstevel@tonic-gate #define	EC_NODE_MISMATCH	5
61*7c478bd9Sstevel@tonic-gate #define	EC_FAILURE		6
62*7c478bd9Sstevel@tonic-gate #define	EC_PICL_ERR		7
63*7c478bd9Sstevel@tonic-gate #define	EC_TABLE_MISMATCH	8
64*7c478bd9Sstevel@tonic-gate #define	EC_ROW_MISMATCH		9
65*7c478bd9Sstevel@tonic-gate #define	EC_ROW_EMPTY		10
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /*
68*7c478bd9Sstevel@tonic-gate  * Error message texts
69*7c478bd9Sstevel@tonic-gate  */
70*7c478bd9Sstevel@tonic-gate static	char	*err_msg[] = {
71*7c478bd9Sstevel@tonic-gate 	"%s: Syntax OK",					/* 0 */
72*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Insufficient token\n",		/* 1 */
73*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Syntax error\n",			/* 2 */
74*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Unsupported or missing version\n",	/* 3 */
75*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Illegal use of nodepath or namepath\n",	/* 4 */
76*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Node and endnode mismatch\n",		/* 5 */
77*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: General system failure\n",		/* 6 */
78*7c478bd9Sstevel@tonic-gate 	"%s: PICL error code %d\n",				/* 7 */
79*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Table and endtable mismatch\n",	/* 8 */
80*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Row and endrow mismatch\n",		/* 9 */
81*7c478bd9Sstevel@tonic-gate 	"%s::%s[line %d]: Row has no entries \n"		/* 10 */
82*7c478bd9Sstevel@tonic-gate };
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate /* token per directive */
85*7c478bd9Sstevel@tonic-gate #define	TOK_CLASSPATH	0
86*7c478bd9Sstevel@tonic-gate #define	TOK_NAMEPATH	1
87*7c478bd9Sstevel@tonic-gate #define	TOK_NODE	2
88*7c478bd9Sstevel@tonic-gate #define	TOK_ENDNODE	3
89*7c478bd9Sstevel@tonic-gate #define	TOK_PROP	4
90*7c478bd9Sstevel@tonic-gate #define	TOK_REFPROP	5
91*7c478bd9Sstevel@tonic-gate #define	TOK_VERSION	6
92*7c478bd9Sstevel@tonic-gate #define	TOK_REFNODE	7
93*7c478bd9Sstevel@tonic-gate #define	TOK_VERBOSE	8
94*7c478bd9Sstevel@tonic-gate #define	TOK_TABLE	9
95*7c478bd9Sstevel@tonic-gate #define	TOK_ENDTABLE	10
96*7c478bd9Sstevel@tonic-gate #define	TOK_ROW		11
97*7c478bd9Sstevel@tonic-gate #define	TOK_ENDROW	12
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate static const char	*tokens[] = {
100*7c478bd9Sstevel@tonic-gate 	"_class",	/* _CLASS:<classpath> */
101*7c478bd9Sstevel@tonic-gate 	"name",		/* NAME:<namepath> */
102*7c478bd9Sstevel@tonic-gate 	"node",		/* NODE <name> <class> */
103*7c478bd9Sstevel@tonic-gate 	"endnode",	/* ENDNODE */
104*7c478bd9Sstevel@tonic-gate 	"prop",		/* PROP <name> <type> <access_mode> <size> <value> */
105*7c478bd9Sstevel@tonic-gate 	"refprop",	/* REFPROP <prop> <destnode> */
106*7c478bd9Sstevel@tonic-gate 	"version",	/* VERSION <version_number> */
107*7c478bd9Sstevel@tonic-gate 	"refnode",	/* REFNODE <node> <class> WITH <destnode> */
108*7c478bd9Sstevel@tonic-gate 	"verbose",	/* VERBOSE <level> */
109*7c478bd9Sstevel@tonic-gate 	"table",	/* TABLE   <table_prop_name> */
110*7c478bd9Sstevel@tonic-gate 	"endtable",	/* ENDTABLE */
111*7c478bd9Sstevel@tonic-gate 	"row",		/* ROW  */
112*7c478bd9Sstevel@tonic-gate 	"endrow"	/* ENDROW */
113*7c478bd9Sstevel@tonic-gate };
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate #define	BUF_SIZE_MAX	1024
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate /*
118*7c478bd9Sstevel@tonic-gate  * print error message
119*7c478bd9Sstevel@tonic-gate  */
120*7c478bd9Sstevel@tonic-gate /*VARARGS2*/
121*7c478bd9Sstevel@tonic-gate static void
122*7c478bd9Sstevel@tonic-gate verbose_log(int pri, const char *fmt, ...)
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate 	va_list	ap;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
127*7c478bd9Sstevel@tonic-gate 	vsyslog(pri, fmt, ap);
128*7c478bd9Sstevel@tonic-gate 	va_end(ap);
129*7c478bd9Sstevel@tonic-gate }
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate /*
132*7c478bd9Sstevel@tonic-gate  * Undo the commands which have created valid node/prop handle
133*7c478bd9Sstevel@tonic-gate  * The undo order is from last command to the first command.
134*7c478bd9Sstevel@tonic-gate  */
135*7c478bd9Sstevel@tonic-gate static void
136*7c478bd9Sstevel@tonic-gate undo_commands(cmdbuf_t *cmds, int last_cmd_index)
137*7c478bd9Sstevel@tonic-gate {
138*7c478bd9Sstevel@tonic-gate 	int 		i;
139*7c478bd9Sstevel@tonic-gate 	command_t	*com = cmds->commands;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	for (i = last_cmd_index; i >= 0; i--) {
142*7c478bd9Sstevel@tonic-gate 		switch (com[i].type) {
143*7c478bd9Sstevel@tonic-gate 		case TOK_NODE:
144*7c478bd9Sstevel@tonic-gate 			if (com[i].nodecmd_nodeh == NULL)
145*7c478bd9Sstevel@tonic-gate 				break;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 			(void) ptree_delete_node(com[i].nodecmd_nodeh);
148*7c478bd9Sstevel@tonic-gate 			(void) ptree_destroy_node(com[i].nodecmd_nodeh);
149*7c478bd9Sstevel@tonic-gate 			break;
150*7c478bd9Sstevel@tonic-gate 		case TOK_REFNODE:
151*7c478bd9Sstevel@tonic-gate 			if (com[i].refnodecmd_nodeh == NULL)
152*7c478bd9Sstevel@tonic-gate 				break;
153*7c478bd9Sstevel@tonic-gate 			(void) ptree_delete_node(com[i].refnodecmd_nodeh);
154*7c478bd9Sstevel@tonic-gate 			(void) ptree_destroy_node(com[i].refnodecmd_nodeh);
155*7c478bd9Sstevel@tonic-gate 			break;
156*7c478bd9Sstevel@tonic-gate 		case TOK_PROP:
157*7c478bd9Sstevel@tonic-gate 			if (com[i].propcmd_proph == NULL)
158*7c478bd9Sstevel@tonic-gate 				break;
159*7c478bd9Sstevel@tonic-gate 			(void) ptree_delete_prop(com[i].propcmd_proph);
160*7c478bd9Sstevel@tonic-gate 			(void) ptree_destroy_prop(com[i].propcmd_proph);
161*7c478bd9Sstevel@tonic-gate 			break;
162*7c478bd9Sstevel@tonic-gate 		case TOK_REFPROP:
163*7c478bd9Sstevel@tonic-gate 			if (com[i].refpropcmd_proph == NULL)
164*7c478bd9Sstevel@tonic-gate 				break;
165*7c478bd9Sstevel@tonic-gate 			(void) ptree_delete_prop(com[i].refpropcmd_proph);
166*7c478bd9Sstevel@tonic-gate 			(void) ptree_destroy_prop(com[i].refpropcmd_proph);
167*7c478bd9Sstevel@tonic-gate 			break;
168*7c478bd9Sstevel@tonic-gate 		case TOK_TABLE:
169*7c478bd9Sstevel@tonic-gate 			if ((com[i].tablecmd_tblh == NULL) ||
170*7c478bd9Sstevel@tonic-gate 			    (com[i].tablecmd_newtbl == 0))
171*7c478bd9Sstevel@tonic-gate 				break;
172*7c478bd9Sstevel@tonic-gate 			(void) ptree_delete_prop(com[i].tablecmd_tblh);
173*7c478bd9Sstevel@tonic-gate 			(void) ptree_destroy_prop(com[i].tablecmd_tblh);
174*7c478bd9Sstevel@tonic-gate 			break;
175*7c478bd9Sstevel@tonic-gate 		case TOK_ENDTABLE:
176*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
177*7c478bd9Sstevel@tonic-gate 		case TOK_ROW:
178*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
179*7c478bd9Sstevel@tonic-gate 		case TOK_ENDROW:
180*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
181*7c478bd9Sstevel@tonic-gate 		case TOK_NAMEPATH:
182*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
183*7c478bd9Sstevel@tonic-gate 		case TOK_CLASSPATH:
184*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
185*7c478bd9Sstevel@tonic-gate 		case TOK_ENDNODE:
186*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
187*7c478bd9Sstevel@tonic-gate 		case TOK_VERBOSE:
188*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
189*7c478bd9Sstevel@tonic-gate 		default:
190*7c478bd9Sstevel@tonic-gate 			break;
191*7c478bd9Sstevel@tonic-gate 		}
192*7c478bd9Sstevel@tonic-gate 	}
193*7c478bd9Sstevel@tonic-gate }
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate /*
196*7c478bd9Sstevel@tonic-gate  * Get the token index from the tokens table
197*7c478bd9Sstevel@tonic-gate  */
198*7c478bd9Sstevel@tonic-gate static int
199*7c478bd9Sstevel@tonic-gate get_token_id(char *t)
200*7c478bd9Sstevel@tonic-gate {
201*7c478bd9Sstevel@tonic-gate 	int	i;
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < sizeof (tokens)/ sizeof (char *); ++i)
204*7c478bd9Sstevel@tonic-gate 		if (strcasecmp(tokens[i], t) == 0)
205*7c478bd9Sstevel@tonic-gate 			return (i);
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	return (-1);
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate /*
211*7c478bd9Sstevel@tonic-gate  * Check the version syntax and set the version_no
212*7c478bd9Sstevel@tonic-gate  *
213*7c478bd9Sstevel@tonic-gate  * VERSION <version_num> --   specify the configuration version
214*7c478bd9Sstevel@tonic-gate  */
215*7c478bd9Sstevel@tonic-gate static int
216*7c478bd9Sstevel@tonic-gate parse_version(cmdbuf_t *cmds, char *line)
217*7c478bd9Sstevel@tonic-gate {
218*7c478bd9Sstevel@tonic-gate 	char	*tok;
219*7c478bd9Sstevel@tonic-gate 	char	*vertok;
220*7c478bd9Sstevel@tonic-gate 	char	*last;
221*7c478bd9Sstevel@tonic-gate 	char	*endptr;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	/* get the VERSION directive */
224*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
225*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
226*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	/* get the version number */
229*7c478bd9Sstevel@tonic-gate 	vertok = strtok_r(last, WHITESPACE, &last);
230*7c478bd9Sstevel@tonic-gate 	if (vertok == NULL)
231*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	cmds->version_no = (float)strtod(vertok, &endptr);
234*7c478bd9Sstevel@tonic-gate 	if (endptr != (vertok + strlen(vertok)))
235*7c478bd9Sstevel@tonic-gate 		return (EC_UNSUPPORTED);
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	if (cmds->version_no > (float)SUPPORTED_VERSION_NUM)
238*7c478bd9Sstevel@tonic-gate 		return (EC_UNSUPPORTED);
239*7c478bd9Sstevel@tonic-gate 
240*7c478bd9Sstevel@tonic-gate 	/* check if more tokens */
241*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
242*7c478bd9Sstevel@tonic-gate 	if (tok != NULL)
243*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
246*7c478bd9Sstevel@tonic-gate }
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate /*
249*7c478bd9Sstevel@tonic-gate  * free path_cmd_t
250*7c478bd9Sstevel@tonic-gate  */
251*7c478bd9Sstevel@tonic-gate static void
252*7c478bd9Sstevel@tonic-gate free_path(command_t *command)
253*7c478bd9Sstevel@tonic-gate {
254*7c478bd9Sstevel@tonic-gate 	free(command->pathcmd_name);
255*7c478bd9Sstevel@tonic-gate }
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate  * Check the path syntax
259*7c478bd9Sstevel@tonic-gate  * NAMEPATH:<namepath> --     gives the anchor node
260*7c478bd9Sstevel@tonic-gate  * or
261*7c478bd9Sstevel@tonic-gate  * CLASSPATH:<classpath> --   gives the anchor node
262*7c478bd9Sstevel@tonic-gate  */
263*7c478bd9Sstevel@tonic-gate static int
264*7c478bd9Sstevel@tonic-gate parse_path(char *line, command_t *command)
265*7c478bd9Sstevel@tonic-gate {
266*7c478bd9Sstevel@tonic-gate 	char	*tok;
267*7c478bd9Sstevel@tonic-gate 	char	*pathtok;
268*7c478bd9Sstevel@tonic-gate 	char	*last;
269*7c478bd9Sstevel@tonic-gate 
270*7c478bd9Sstevel@tonic-gate 	pathtok = strtok_r(line, WHITESPACE, &last);
271*7c478bd9Sstevel@tonic-gate 	if (pathtok == NULL)
272*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	/* check if more tokens */
275*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
276*7c478bd9Sstevel@tonic-gate 	if (tok != NULL)
277*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	command->pathcmd_name = strdup(pathtok);
280*7c478bd9Sstevel@tonic-gate 	if (command->pathcmd_name == NULL)
281*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
284*7c478bd9Sstevel@tonic-gate }
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate /*
287*7c478bd9Sstevel@tonic-gate  * Process the path command and return PICL node handle
288*7c478bd9Sstevel@tonic-gate  */
289*7c478bd9Sstevel@tonic-gate static int
290*7c478bd9Sstevel@tonic-gate process_path(command_t *command, picl_nodehdl_t *nodeh)
291*7c478bd9Sstevel@tonic-gate {
292*7c478bd9Sstevel@tonic-gate 	int	err;
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	err = ptree_get_node_by_path(command->pathcmd_name, nodeh);
295*7c478bd9Sstevel@tonic-gate 	return (err);
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate /*
299*7c478bd9Sstevel@tonic-gate  * free node_cmd_t
300*7c478bd9Sstevel@tonic-gate  */
301*7c478bd9Sstevel@tonic-gate static void
302*7c478bd9Sstevel@tonic-gate free_node(command_t *command)
303*7c478bd9Sstevel@tonic-gate {
304*7c478bd9Sstevel@tonic-gate 	free(command->nodecmd_nodename);
305*7c478bd9Sstevel@tonic-gate 	free(command->nodecmd_classname);
306*7c478bd9Sstevel@tonic-gate }
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate /*
309*7c478bd9Sstevel@tonic-gate  * Check the NODE syntax
310*7c478bd9Sstevel@tonic-gate  * NODE <name> <class>
311*7c478bd9Sstevel@tonic-gate  */
312*7c478bd9Sstevel@tonic-gate static int
313*7c478bd9Sstevel@tonic-gate parse_node(char *line, command_t *command)
314*7c478bd9Sstevel@tonic-gate {
315*7c478bd9Sstevel@tonic-gate 	char	*tok;
316*7c478bd9Sstevel@tonic-gate 	char	*nametok;
317*7c478bd9Sstevel@tonic-gate 	char	*classtok;
318*7c478bd9Sstevel@tonic-gate 	char	*last;
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 	/* get the NODE directive */
321*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
322*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
323*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	/* get name */
326*7c478bd9Sstevel@tonic-gate 	nametok = strtok_r(last, WHITESPACE, &last);
327*7c478bd9Sstevel@tonic-gate 	if (nametok == NULL)
328*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	classtok = strtok_r(last, WHITESPACE, &last);
331*7c478bd9Sstevel@tonic-gate 	if (classtok == NULL)
332*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	/* check if more tokens */
335*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
336*7c478bd9Sstevel@tonic-gate 	if (tok != NULL)
337*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	command->nodecmd_nodename = strdup(nametok);
340*7c478bd9Sstevel@tonic-gate 	command->nodecmd_classname = strdup(classtok);
341*7c478bd9Sstevel@tonic-gate 	command->nodecmd_nodeh = NULL;
342*7c478bd9Sstevel@tonic-gate 	if ((command->nodecmd_nodename == NULL) ||
343*7c478bd9Sstevel@tonic-gate 	    (command->nodecmd_classname == NULL))
344*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
347*7c478bd9Sstevel@tonic-gate }
348*7c478bd9Sstevel@tonic-gate 
349*7c478bd9Sstevel@tonic-gate /*
350*7c478bd9Sstevel@tonic-gate  * Process the NODE command and return PICL node handle
351*7c478bd9Sstevel@tonic-gate  */
352*7c478bd9Sstevel@tonic-gate static int
353*7c478bd9Sstevel@tonic-gate process_node(command_t *command, picl_nodehdl_t parh, picl_nodehdl_t *nodeh)
354*7c478bd9Sstevel@tonic-gate {
355*7c478bd9Sstevel@tonic-gate 	int	err;
356*7c478bd9Sstevel@tonic-gate 
357*7c478bd9Sstevel@tonic-gate 	err = ptree_create_and_add_node(parh, command->nodecmd_nodename,
358*7c478bd9Sstevel@tonic-gate 	    command->nodecmd_classname, nodeh);
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	if (err == PICL_SUCCESS)
361*7c478bd9Sstevel@tonic-gate 		command->nodecmd_nodeh = *nodeh;
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	return (err);
364*7c478bd9Sstevel@tonic-gate }
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate /*
367*7c478bd9Sstevel@tonic-gate  * get the PICL property type
368*7c478bd9Sstevel@tonic-gate  */
369*7c478bd9Sstevel@tonic-gate static int
370*7c478bd9Sstevel@tonic-gate getpicltype(char *type)
371*7c478bd9Sstevel@tonic-gate {
372*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(type, KEYWORD_INT_TYPE) == 0)
373*7c478bd9Sstevel@tonic-gate 		return (PICL_PTYPE_INT);
374*7c478bd9Sstevel@tonic-gate 	else if (strcasecmp(type, KEYWORD_UINT_TYPE) == 0)
375*7c478bd9Sstevel@tonic-gate 		return (PICL_PTYPE_UNSIGNED_INT);
376*7c478bd9Sstevel@tonic-gate 	else if (strcasecmp(type, KEYWORD_FLOAT_TYPE) == 0)
377*7c478bd9Sstevel@tonic-gate 		return (PICL_PTYPE_FLOAT);
378*7c478bd9Sstevel@tonic-gate 	else if (strcasecmp(type, KEYWORD_STRING_TYPE) == 0)
379*7c478bd9Sstevel@tonic-gate 		return (PICL_PTYPE_CHARSTRING);
380*7c478bd9Sstevel@tonic-gate 	else if (strcasecmp(type, KEYWORD_VOID_TYPE) == 0)
381*7c478bd9Sstevel@tonic-gate 		return (PICL_PTYPE_VOID);
382*7c478bd9Sstevel@tonic-gate 	else
383*7c478bd9Sstevel@tonic-gate 		return (-1);
384*7c478bd9Sstevel@tonic-gate }
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate /*
387*7c478bd9Sstevel@tonic-gate  * get the PICL accessmode mode
388*7c478bd9Sstevel@tonic-gate  */
389*7c478bd9Sstevel@tonic-gate static int
390*7c478bd9Sstevel@tonic-gate getpiclmode(char *mode)
391*7c478bd9Sstevel@tonic-gate {
392*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(mode, KEYWORD_READ_MODE) == 0)
393*7c478bd9Sstevel@tonic-gate 		return (PICL_READ);
394*7c478bd9Sstevel@tonic-gate 	else if (strcasecmp(mode, KEYWORD_WRITE_MODE) == 0)
395*7c478bd9Sstevel@tonic-gate 		return (PICL_WRITE);
396*7c478bd9Sstevel@tonic-gate 	else if (strcasecmp(mode, KEYWORD_READWRITE_MODE) == 0)
397*7c478bd9Sstevel@tonic-gate 		return (PICL_READ|PICL_WRITE);
398*7c478bd9Sstevel@tonic-gate 	else
399*7c478bd9Sstevel@tonic-gate 		return (-1);
400*7c478bd9Sstevel@tonic-gate }
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate /*
403*7c478bd9Sstevel@tonic-gate  * check if the size and value are valid given by the prop type
404*7c478bd9Sstevel@tonic-gate  */
405*7c478bd9Sstevel@tonic-gate static int
406*7c478bd9Sstevel@tonic-gate validate_size_and_cvt_val(void *outbuf, size_t size, int type, char *val)
407*7c478bd9Sstevel@tonic-gate {
408*7c478bd9Sstevel@tonic-gate 	int64_t 	llval;
409*7c478bd9Sstevel@tonic-gate 	int32_t		intval;
410*7c478bd9Sstevel@tonic-gate 	int16_t		sval;
411*7c478bd9Sstevel@tonic-gate 	int8_t		cval;
412*7c478bd9Sstevel@tonic-gate 	uint64_t 	ullval;
413*7c478bd9Sstevel@tonic-gate 	uint32_t	uintval;
414*7c478bd9Sstevel@tonic-gate 	uint16_t	usval;
415*7c478bd9Sstevel@tonic-gate 	uint8_t		ucval;
416*7c478bd9Sstevel@tonic-gate 	float		fval;
417*7c478bd9Sstevel@tonic-gate 	double		dval;
418*7c478bd9Sstevel@tonic-gate 	char		*endptr;
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate 	switch (type) {
421*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_CHARSTRING:
422*7c478bd9Sstevel@tonic-gate 		break;
423*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_INT:
424*7c478bd9Sstevel@tonic-gate 		switch (size) {
425*7c478bd9Sstevel@tonic-gate 		case sizeof (int64_t):
426*7c478bd9Sstevel@tonic-gate 			llval = strtoll(val, &endptr, 0);
427*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
428*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
429*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &llval, size);
430*7c478bd9Sstevel@tonic-gate 			break;
431*7c478bd9Sstevel@tonic-gate 		case sizeof (int32_t):
432*7c478bd9Sstevel@tonic-gate 			intval = strtol(val, &endptr, 0);
433*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
434*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
435*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &intval, size);
436*7c478bd9Sstevel@tonic-gate 			break;
437*7c478bd9Sstevel@tonic-gate 		case sizeof (int16_t):
438*7c478bd9Sstevel@tonic-gate 			sval = (int16_t)strtol(val, &endptr, 0);
439*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
440*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
441*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &sval, size);
442*7c478bd9Sstevel@tonic-gate 			break;
443*7c478bd9Sstevel@tonic-gate 		case sizeof (int8_t):
444*7c478bd9Sstevel@tonic-gate 			cval = (int8_t)strtol(val, &endptr, 0);
445*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
446*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
447*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &cval, size);
448*7c478bd9Sstevel@tonic-gate 			break;
449*7c478bd9Sstevel@tonic-gate 		default:	/* invalid size */
450*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
451*7c478bd9Sstevel@tonic-gate 		}
452*7c478bd9Sstevel@tonic-gate 		break;
453*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_UNSIGNED_INT:
454*7c478bd9Sstevel@tonic-gate 		switch (size) {
455*7c478bd9Sstevel@tonic-gate 		case sizeof (uint64_t):
456*7c478bd9Sstevel@tonic-gate 			ullval = strtoull(val, &endptr, 0);
457*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
458*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
459*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &ullval, size);
460*7c478bd9Sstevel@tonic-gate 			break;
461*7c478bd9Sstevel@tonic-gate 		case sizeof (uint32_t):
462*7c478bd9Sstevel@tonic-gate 			uintval = strtoul(val, &endptr, 0);
463*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
464*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
465*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &uintval, size);
466*7c478bd9Sstevel@tonic-gate 			break;
467*7c478bd9Sstevel@tonic-gate 		case sizeof (uint16_t):
468*7c478bd9Sstevel@tonic-gate 			usval = (uint16_t)strtoul(val, &endptr, 0);
469*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
470*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
471*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &usval, size);
472*7c478bd9Sstevel@tonic-gate 			break;
473*7c478bd9Sstevel@tonic-gate 		case sizeof (uint8_t):
474*7c478bd9Sstevel@tonic-gate 			ucval = (uint8_t)strtoul(val, &endptr, 0);
475*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
476*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
477*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &ucval, size);
478*7c478bd9Sstevel@tonic-gate 			break;
479*7c478bd9Sstevel@tonic-gate 		default:	/* invalid size */
480*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
481*7c478bd9Sstevel@tonic-gate 		}
482*7c478bd9Sstevel@tonic-gate 		break;
483*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_FLOAT:
484*7c478bd9Sstevel@tonic-gate 		switch (size) {
485*7c478bd9Sstevel@tonic-gate 		case sizeof (double):
486*7c478bd9Sstevel@tonic-gate 			dval = strtod(val, &endptr);
487*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
488*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
489*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &dval, size);
490*7c478bd9Sstevel@tonic-gate 			break;
491*7c478bd9Sstevel@tonic-gate 		case sizeof (float):
492*7c478bd9Sstevel@tonic-gate 			fval = (float)strtod(val, &endptr);
493*7c478bd9Sstevel@tonic-gate 			if (endptr != (val + strlen(val)))
494*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
495*7c478bd9Sstevel@tonic-gate 			(void) memcpy(outbuf, &fval, size);
496*7c478bd9Sstevel@tonic-gate 			break;
497*7c478bd9Sstevel@tonic-gate 		default:	/* invalid size */
498*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
499*7c478bd9Sstevel@tonic-gate 		}
500*7c478bd9Sstevel@tonic-gate 		break;
501*7c478bd9Sstevel@tonic-gate 	default:	/* not supported type */
502*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
503*7c478bd9Sstevel@tonic-gate 	}
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
506*7c478bd9Sstevel@tonic-gate }
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate /*
509*7c478bd9Sstevel@tonic-gate  * free prop_cmd_t
510*7c478bd9Sstevel@tonic-gate  */
511*7c478bd9Sstevel@tonic-gate static void
512*7c478bd9Sstevel@tonic-gate free_prop(command_t *command)
513*7c478bd9Sstevel@tonic-gate {
514*7c478bd9Sstevel@tonic-gate 	free(command->propcmd_pname);
515*7c478bd9Sstevel@tonic-gate 	if (command->propcmd_type != PICL_PTYPE_VOID)
516*7c478bd9Sstevel@tonic-gate 		free(command->propcmd_valbuf);
517*7c478bd9Sstevel@tonic-gate }
518*7c478bd9Sstevel@tonic-gate 
519*7c478bd9Sstevel@tonic-gate /*
520*7c478bd9Sstevel@tonic-gate  * return the string token in two double quotes
521*7c478bd9Sstevel@tonic-gate  * The current version won't support multiple-line string
522*7c478bd9Sstevel@tonic-gate  */
523*7c478bd9Sstevel@tonic-gate static int
524*7c478bd9Sstevel@tonic-gate get_string_token(char *line, char **valtok)
525*7c478bd9Sstevel@tonic-gate {
526*7c478bd9Sstevel@tonic-gate 	char	*optr;	/* ptr to the open quote */
527*7c478bd9Sstevel@tonic-gate 	char	*cptr;	/* ptr to the close quote */
528*7c478bd9Sstevel@tonic-gate 	char	*ptr;
529*7c478bd9Sstevel@tonic-gate 	char	*tmpbuf;
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	if (line == NULL)
532*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	/* skipping leading white spaces */
535*7c478bd9Sstevel@tonic-gate 	optr = line;
536*7c478bd9Sstevel@tonic-gate 	while ((*optr == ' ') || (*optr == '\t') || (*optr == '\n'))
537*7c478bd9Sstevel@tonic-gate 		optr++;
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	/* reach end of string */
540*7c478bd9Sstevel@tonic-gate 	if (*optr == '\0')
541*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 	/* it's not an open double quote */
544*7c478bd9Sstevel@tonic-gate 	if (*optr != '"')
545*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	/* skipping ending white spaces */
548*7c478bd9Sstevel@tonic-gate 	cptr = line + strlen(line) - 1;
549*7c478bd9Sstevel@tonic-gate 	while ((*cptr == ' ') || (*cptr == '\t') || (*cptr == '\n'))
550*7c478bd9Sstevel@tonic-gate 		cptr--;
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 	/* it's not an close double quote */
553*7c478bd9Sstevel@tonic-gate 	if (*cptr != '"')
554*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate 	/* close double quote is missing */
557*7c478bd9Sstevel@tonic-gate 	if (cptr == optr)
558*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 	/* replace close qoute by null to make a string */
561*7c478bd9Sstevel@tonic-gate 	*cptr = '\0';
562*7c478bd9Sstevel@tonic-gate 	/* move the begin pointer to the first char of string */
563*7c478bd9Sstevel@tonic-gate 	optr++;
564*7c478bd9Sstevel@tonic-gate 
565*7c478bd9Sstevel@tonic-gate 	tmpbuf = malloc(strlen(optr) + 1);
566*7c478bd9Sstevel@tonic-gate 	if (tmpbuf == NULL)
567*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 	for (ptr = tmpbuf; *optr != '\0'; ptr++, optr++) {
570*7c478bd9Sstevel@tonic-gate 		/* if escape character, go to next character */
571*7c478bd9Sstevel@tonic-gate 		if (*optr == '\\') {
572*7c478bd9Sstevel@tonic-gate 			optr++;
573*7c478bd9Sstevel@tonic-gate 			if (*optr == '\0') {	/* for exampe, "xxx\" */
574*7c478bd9Sstevel@tonic-gate 				free(tmpbuf);
575*7c478bd9Sstevel@tonic-gate 				return (EC_SYNTAX_ERR);
576*7c478bd9Sstevel@tonic-gate 			}
577*7c478bd9Sstevel@tonic-gate 		}
578*7c478bd9Sstevel@tonic-gate 		*ptr = *optr;
579*7c478bd9Sstevel@tonic-gate 	}
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate 	*ptr = '\0';
582*7c478bd9Sstevel@tonic-gate 	*valtok = tmpbuf;
583*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
584*7c478bd9Sstevel@tonic-gate }
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate /*
587*7c478bd9Sstevel@tonic-gate  * Check the PROP syntax
588*7c478bd9Sstevel@tonic-gate  * PROP <name> <type> <access_mode> [<size> <value>]
589*7c478bd9Sstevel@tonic-gate  * supported prop types: void, int, uint, float, string
590*7c478bd9Sstevel@tonic-gate  * supported prop access_modes: r, w, rw
591*7c478bd9Sstevel@tonic-gate  * For void prop, <size> and <value> are not needed
592*7c478bd9Sstevel@tonic-gate  * For string prop, <size> will be set the actual string size if <size>
593*7c478bd9Sstevel@tonic-gate  * is 0
594*7c478bd9Sstevel@tonic-gate  */
595*7c478bd9Sstevel@tonic-gate static int
596*7c478bd9Sstevel@tonic-gate parse_prop(char *line, command_t *command)
597*7c478bd9Sstevel@tonic-gate {
598*7c478bd9Sstevel@tonic-gate 	char	*tok;
599*7c478bd9Sstevel@tonic-gate 	char	*pnametok;
600*7c478bd9Sstevel@tonic-gate 	int	typetok;
601*7c478bd9Sstevel@tonic-gate 	size_t	sizetok;
602*7c478bd9Sstevel@tonic-gate 	int	modetok;
603*7c478bd9Sstevel@tonic-gate 	char	*valtok;
604*7c478bd9Sstevel@tonic-gate 	char	*last;
605*7c478bd9Sstevel@tonic-gate 	char	*endptr;
606*7c478bd9Sstevel@tonic-gate 	int	err;
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 	/* get the PROP directive */
609*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
610*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
611*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 	/* get the property name */
614*7c478bd9Sstevel@tonic-gate 	pnametok = strtok_r(last, WHITESPACE, &last);
615*7c478bd9Sstevel@tonic-gate 	if (pnametok == NULL)
616*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
617*7c478bd9Sstevel@tonic-gate 
618*7c478bd9Sstevel@tonic-gate 	/* get the type */
619*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
620*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
621*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	if ((typetok = getpicltype(tok)) < 0)
624*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	/* get mode */
627*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
628*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
629*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate 	if ((modetok = getpiclmode(tok)) < 0)
632*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
633*7c478bd9Sstevel@tonic-gate 
634*7c478bd9Sstevel@tonic-gate 	if (typetok == PICL_PTYPE_VOID) {
635*7c478bd9Sstevel@tonic-gate 		/* ignore the rest of arguments */
636*7c478bd9Sstevel@tonic-gate 		command->propcmd_valbuf = NULL;
637*7c478bd9Sstevel@tonic-gate 		command->propcmd_pname = strdup(pnametok);
638*7c478bd9Sstevel@tonic-gate 		if (command->propcmd_pname == NULL)
639*7c478bd9Sstevel@tonic-gate 			return (EC_FAILURE);
640*7c478bd9Sstevel@tonic-gate 		command->propcmd_type = typetok;
641*7c478bd9Sstevel@tonic-gate 		command->propcmd_accessmode = modetok;
642*7c478bd9Sstevel@tonic-gate 		command->propcmd_size = 0;
643*7c478bd9Sstevel@tonic-gate 		command->propcmd_proph = NULL;
644*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_OK);
645*7c478bd9Sstevel@tonic-gate 	}
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 	/* get size */
648*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
649*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
650*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
651*7c478bd9Sstevel@tonic-gate 
652*7c478bd9Sstevel@tonic-gate 	sizetok = (size_t)strtol(tok, &endptr, 0);
653*7c478bd9Sstevel@tonic-gate 	if (endptr != (tok + strlen(tok)))
654*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
655*7c478bd9Sstevel@tonic-gate 
656*7c478bd9Sstevel@tonic-gate 	/* get val */
657*7c478bd9Sstevel@tonic-gate 	if (typetok == PICL_PTYPE_CHARSTRING) {
658*7c478bd9Sstevel@tonic-gate 		err = get_string_token(last, &valtok);
659*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
660*7c478bd9Sstevel@tonic-gate 			return (err);
661*7c478bd9Sstevel@tonic-gate 		if (sizetok == 0)
662*7c478bd9Sstevel@tonic-gate 			sizetok = strlen(valtok) + 1;
663*7c478bd9Sstevel@tonic-gate 		command->propcmd_valbuf = valtok;
664*7c478bd9Sstevel@tonic-gate 	} else {
665*7c478bd9Sstevel@tonic-gate 		valtok = strtok_r(last, WHITESPACE, &last);
666*7c478bd9Sstevel@tonic-gate 		if (valtok == NULL)
667*7c478bd9Sstevel@tonic-gate 			return (EC_INSUFFICIENT_TOKEN);
668*7c478bd9Sstevel@tonic-gate 		/* check if more tokens */
669*7c478bd9Sstevel@tonic-gate 		tok = strtok_r(last, WHITESPACE, &last);
670*7c478bd9Sstevel@tonic-gate 		if (tok != NULL)
671*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
672*7c478bd9Sstevel@tonic-gate 		command->propcmd_valbuf = malloc(sizetok);
673*7c478bd9Sstevel@tonic-gate 		if (command->propcmd_valbuf == NULL)
674*7c478bd9Sstevel@tonic-gate 			return (EC_FAILURE);
675*7c478bd9Sstevel@tonic-gate 		err = validate_size_and_cvt_val(command->propcmd_valbuf,
676*7c478bd9Sstevel@tonic-gate 		    sizetok, typetok, valtok);
677*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK) {
678*7c478bd9Sstevel@tonic-gate 			free(command->propcmd_valbuf);
679*7c478bd9Sstevel@tonic-gate 			return (err);
680*7c478bd9Sstevel@tonic-gate 		}
681*7c478bd9Sstevel@tonic-gate 	}
682*7c478bd9Sstevel@tonic-gate 
683*7c478bd9Sstevel@tonic-gate 	command->propcmd_pname = strdup(pnametok);
684*7c478bd9Sstevel@tonic-gate 	if (command->propcmd_pname == NULL)
685*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
686*7c478bd9Sstevel@tonic-gate 	command->propcmd_type = typetok;
687*7c478bd9Sstevel@tonic-gate 	command->propcmd_accessmode = modetok;
688*7c478bd9Sstevel@tonic-gate 	command->propcmd_size = sizetok;
689*7c478bd9Sstevel@tonic-gate 	command->propcmd_proph = NULL;
690*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
691*7c478bd9Sstevel@tonic-gate }
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate /*
694*7c478bd9Sstevel@tonic-gate  * Add a property to the row, the row gets added to the node at endrow
695*7c478bd9Sstevel@tonic-gate  */
696*7c478bd9Sstevel@tonic-gate static int
697*7c478bd9Sstevel@tonic-gate add_proph_to_row(command_t *command, picl_prophdl_t proph)
698*7c478bd9Sstevel@tonic-gate {
699*7c478bd9Sstevel@tonic-gate 	if (command->rowcmd_index >= command->rowcmd_nproph)
700*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
701*7c478bd9Sstevel@tonic-gate 	command->rowcmd_prophs[command->rowcmd_index] = proph;
702*7c478bd9Sstevel@tonic-gate 	command->rowcmd_index++;
703*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
704*7c478bd9Sstevel@tonic-gate }
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate /*
707*7c478bd9Sstevel@tonic-gate  * Process the PROP command and add the specified property under the given
708*7c478bd9Sstevel@tonic-gate  * node handle
709*7c478bd9Sstevel@tonic-gate  */
710*7c478bd9Sstevel@tonic-gate static int
711*7c478bd9Sstevel@tonic-gate process_prop(cmdbuf_t *cmds, command_t *command, picl_nodehdl_t nodeh)
712*7c478bd9Sstevel@tonic-gate {
713*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
714*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t		proph;
715*7c478bd9Sstevel@tonic-gate 	int			err;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 	/* prop in discarded row */
718*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_row_block &&
719*7c478bd9Sstevel@tonic-gate 	    cmds->commands[cmds->current_row].rowcmd_nproph == 0)
720*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
723*7c478bd9Sstevel@tonic-gate 	    command->propcmd_type, command->propcmd_accessmode,
724*7c478bd9Sstevel@tonic-gate 	    command->propcmd_size, command->propcmd_pname, NULL,
725*7c478bd9Sstevel@tonic-gate 	    NULL);
726*7c478bd9Sstevel@tonic-gate 
727*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
728*7c478bd9Sstevel@tonic-gate 		return (err);
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 	err = ptree_create_prop(&propinfo, command->propcmd_valbuf, &proph);
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
733*7c478bd9Sstevel@tonic-gate 		return (err);
734*7c478bd9Sstevel@tonic-gate 
735*7c478bd9Sstevel@tonic-gate 	command->propcmd_proph = proph;
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_row_block) {
738*7c478bd9Sstevel@tonic-gate 		err = add_proph_to_row(&cmds->commands[cmds->current_row],
739*7c478bd9Sstevel@tonic-gate 		    proph);
740*7c478bd9Sstevel@tonic-gate 	} else {
741*7c478bd9Sstevel@tonic-gate 		err = ptree_add_prop(nodeh, proph);
742*7c478bd9Sstevel@tonic-gate 	}
743*7c478bd9Sstevel@tonic-gate 
744*7c478bd9Sstevel@tonic-gate 	return (err);
745*7c478bd9Sstevel@tonic-gate }
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate /*
748*7c478bd9Sstevel@tonic-gate  * free refnode_cmd_t
749*7c478bd9Sstevel@tonic-gate  */
750*7c478bd9Sstevel@tonic-gate static void
751*7c478bd9Sstevel@tonic-gate free_refnode(command_t *command)
752*7c478bd9Sstevel@tonic-gate {
753*7c478bd9Sstevel@tonic-gate 	free(command->refnodecmd_name);
754*7c478bd9Sstevel@tonic-gate 	free(command->refnodecmd_class);
755*7c478bd9Sstevel@tonic-gate 	free(command->refnodecmd_dstnode);
756*7c478bd9Sstevel@tonic-gate }
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate /*
759*7c478bd9Sstevel@tonic-gate  * Check the REFNODE syntax
760*7c478bd9Sstevel@tonic-gate  *
761*7c478bd9Sstevel@tonic-gate  * REFNODE <name> <class> with <destnode> -- if <destnode> exists,
762*7c478bd9Sstevel@tonic-gate  * create node with nodename <name> and piclclass <class>
763*7c478bd9Sstevel@tonic-gate  */
764*7c478bd9Sstevel@tonic-gate static int
765*7c478bd9Sstevel@tonic-gate parse_refnode(char *line, command_t *command)
766*7c478bd9Sstevel@tonic-gate {
767*7c478bd9Sstevel@tonic-gate 	char	*tok;
768*7c478bd9Sstevel@tonic-gate 	char	*dsttok;
769*7c478bd9Sstevel@tonic-gate 	char	*classnm;
770*7c478bd9Sstevel@tonic-gate 	char	*nodenm;
771*7c478bd9Sstevel@tonic-gate 	char	*last;
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate 	/* get the directive */
774*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
775*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
776*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 	/* get the nodename */
779*7c478bd9Sstevel@tonic-gate 	nodenm = strtok_r(last, WHITESPACE, &last);
780*7c478bd9Sstevel@tonic-gate 	if (nodenm == NULL)
781*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 	/* get the class */
784*7c478bd9Sstevel@tonic-gate 	classnm = strtok_r(last, WHITESPACE, &last);
785*7c478bd9Sstevel@tonic-gate 	if (classnm == NULL)
786*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	/* get the WITH keyword */
789*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
790*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
791*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(tok, KEYWORD_WITH_STR) != 0)
794*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate 	/* get the dst node */
797*7c478bd9Sstevel@tonic-gate 	dsttok = strtok_r(last, WHITESPACE, &last);
798*7c478bd9Sstevel@tonic-gate 	if (dsttok == NULL)
799*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
800*7c478bd9Sstevel@tonic-gate 
801*7c478bd9Sstevel@tonic-gate 	/* check if more tokens */
802*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
803*7c478bd9Sstevel@tonic-gate 	if (tok != NULL)
804*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
805*7c478bd9Sstevel@tonic-gate 
806*7c478bd9Sstevel@tonic-gate 	command->refnodecmd_name = strdup(nodenm);
807*7c478bd9Sstevel@tonic-gate 	command->refnodecmd_class = strdup(classnm);
808*7c478bd9Sstevel@tonic-gate 	command->refnodecmd_dstnode = strdup(dsttok);
809*7c478bd9Sstevel@tonic-gate 	command->refnodecmd_nodeh = NULL;
810*7c478bd9Sstevel@tonic-gate 	if ((command->refnodecmd_name == NULL) ||
811*7c478bd9Sstevel@tonic-gate 	    (command->refnodecmd_class == NULL) ||
812*7c478bd9Sstevel@tonic-gate 	    (command->refnodecmd_dstnode == NULL))
813*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
816*7c478bd9Sstevel@tonic-gate }
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate /*
819*7c478bd9Sstevel@tonic-gate  * Process the REFNODE command
820*7c478bd9Sstevel@tonic-gate  */
821*7c478bd9Sstevel@tonic-gate static int
822*7c478bd9Sstevel@tonic-gate process_refnode(command_t *command, picl_nodehdl_t parh)
823*7c478bd9Sstevel@tonic-gate {
824*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	dsth;
825*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	nodeh;
826*7c478bd9Sstevel@tonic-gate 	int		err;
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	if ((ptree_get_node_by_path(command->refnodecmd_dstnode,
829*7c478bd9Sstevel@tonic-gate 	    &dsth) == PICL_SUCCESS)) {
830*7c478bd9Sstevel@tonic-gate 		err = ptree_create_and_add_node(parh, command->refnodecmd_name,
831*7c478bd9Sstevel@tonic-gate 		    command->refnodecmd_class, &nodeh);
832*7c478bd9Sstevel@tonic-gate 		if (err == PICL_SUCCESS)
833*7c478bd9Sstevel@tonic-gate 			command->refnodecmd_nodeh = nodeh;
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate 		return (err);
836*7c478bd9Sstevel@tonic-gate 	}
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
839*7c478bd9Sstevel@tonic-gate }
840*7c478bd9Sstevel@tonic-gate 
841*7c478bd9Sstevel@tonic-gate /*
842*7c478bd9Sstevel@tonic-gate  * free refprop_cmd_t
843*7c478bd9Sstevel@tonic-gate  */
844*7c478bd9Sstevel@tonic-gate static void
845*7c478bd9Sstevel@tonic-gate free_refprop(command_t *command)
846*7c478bd9Sstevel@tonic-gate {
847*7c478bd9Sstevel@tonic-gate 	free(command->refpropcmd_pname);
848*7c478bd9Sstevel@tonic-gate 	free(command->refpropcmd_dstnode);
849*7c478bd9Sstevel@tonic-gate }
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate /*
852*7c478bd9Sstevel@tonic-gate  * Check the REFPROP syntax
853*7c478bd9Sstevel@tonic-gate  *
854*7c478bd9Sstevel@tonic-gate  * REFPROP <prop> <destnode> -- creates a reference property to <destnode>
855*7c478bd9Sstevel@tonic-gate  */
856*7c478bd9Sstevel@tonic-gate static int
857*7c478bd9Sstevel@tonic-gate parse_refprop(char *line, command_t *command)
858*7c478bd9Sstevel@tonic-gate {
859*7c478bd9Sstevel@tonic-gate 	char	*tok;
860*7c478bd9Sstevel@tonic-gate 	char	*pnametok;
861*7c478bd9Sstevel@tonic-gate 	char	*dsttok;
862*7c478bd9Sstevel@tonic-gate 	char	*last;
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate 	/* get the REFPROP directive */
865*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
866*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
867*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 	/* get the propname  */
870*7c478bd9Sstevel@tonic-gate 	pnametok = strtok_r(last, WHITESPACE, &last);
871*7c478bd9Sstevel@tonic-gate 	if (pnametok == NULL)
872*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
873*7c478bd9Sstevel@tonic-gate 
874*7c478bd9Sstevel@tonic-gate 	dsttok = strtok_r(last, WHITESPACE, &last);
875*7c478bd9Sstevel@tonic-gate 	if (dsttok == NULL)
876*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 	/* check if more tokens */
879*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
880*7c478bd9Sstevel@tonic-gate 	if (tok != NULL)
881*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate 	command->refpropcmd_pname = strdup(pnametok);
884*7c478bd9Sstevel@tonic-gate 	command->refpropcmd_dstnode = strdup(dsttok);
885*7c478bd9Sstevel@tonic-gate 	command->refpropcmd_proph = NULL;
886*7c478bd9Sstevel@tonic-gate 	if ((command->refpropcmd_pname == NULL) ||
887*7c478bd9Sstevel@tonic-gate 	    (command->refpropcmd_dstnode == NULL))
888*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
891*7c478bd9Sstevel@tonic-gate }
892*7c478bd9Sstevel@tonic-gate 
893*7c478bd9Sstevel@tonic-gate /*
894*7c478bd9Sstevel@tonic-gate  * Process the REFPROP command
895*7c478bd9Sstevel@tonic-gate  */
896*7c478bd9Sstevel@tonic-gate static int
897*7c478bd9Sstevel@tonic-gate process_refprop(cmdbuf_t *cmds, command_t *command, picl_nodehdl_t nodeh)
898*7c478bd9Sstevel@tonic-gate {
899*7c478bd9Sstevel@tonic-gate 	int			err;
900*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t 		dsth;
901*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t 		proph;
902*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
903*7c478bd9Sstevel@tonic-gate 
904*7c478bd9Sstevel@tonic-gate 	/* refprop in discarded row */
905*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_row_block &&
906*7c478bd9Sstevel@tonic-gate 	    cmds->commands[cmds->current_row].rowcmd_nproph == 0)
907*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 	/* try finding the refprop's dstnode */
910*7c478bd9Sstevel@tonic-gate 	err = ptree_get_node_by_path(command->refpropcmd_dstnode, &dsth);
911*7c478bd9Sstevel@tonic-gate 
912*7c478bd9Sstevel@tonic-gate 	/* dstnode doesn't exist, return */
913*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
914*7c478bd9Sstevel@tonic-gate 		return (err);
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 	/* dstnode exists, try adding the refprop to nodeh */
917*7c478bd9Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
918*7c478bd9Sstevel@tonic-gate 		PICL_PTYPE_REFERENCE, PICL_READ, sizeof (picl_nodehdl_t),
919*7c478bd9Sstevel@tonic-gate 		command->refpropcmd_pname, NULL, NULL);
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
922*7c478bd9Sstevel@tonic-gate 		return (err);
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 	err = ptree_create_prop(&propinfo, &dsth, &proph);
925*7c478bd9Sstevel@tonic-gate 
926*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
927*7c478bd9Sstevel@tonic-gate 		return (err);
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	command->refpropcmd_proph = proph;
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_row_block) {
932*7c478bd9Sstevel@tonic-gate 		err = add_proph_to_row(&cmds->commands[cmds->current_row],
933*7c478bd9Sstevel@tonic-gate 		    proph);
934*7c478bd9Sstevel@tonic-gate 	} else {
935*7c478bd9Sstevel@tonic-gate 		err = ptree_add_prop(nodeh, proph);
936*7c478bd9Sstevel@tonic-gate 	}
937*7c478bd9Sstevel@tonic-gate 
938*7c478bd9Sstevel@tonic-gate 	return (err);
939*7c478bd9Sstevel@tonic-gate }
940*7c478bd9Sstevel@tonic-gate 
941*7c478bd9Sstevel@tonic-gate /*
942*7c478bd9Sstevel@tonic-gate  * free table_cmd_t
943*7c478bd9Sstevel@tonic-gate  */
944*7c478bd9Sstevel@tonic-gate static void
945*7c478bd9Sstevel@tonic-gate free_table(command_t *command)
946*7c478bd9Sstevel@tonic-gate {
947*7c478bd9Sstevel@tonic-gate 	if (command->tablecmd_tname)
948*7c478bd9Sstevel@tonic-gate 		free(command->tablecmd_tname);
949*7c478bd9Sstevel@tonic-gate }
950*7c478bd9Sstevel@tonic-gate 
951*7c478bd9Sstevel@tonic-gate /*
952*7c478bd9Sstevel@tonic-gate  * Check the TABLE syntax
953*7c478bd9Sstevel@tonic-gate  * TABLE <table_prop_name>
954*7c478bd9Sstevel@tonic-gate  *
955*7c478bd9Sstevel@tonic-gate  */
956*7c478bd9Sstevel@tonic-gate static int
957*7c478bd9Sstevel@tonic-gate parse_table(char *line, command_t *command)
958*7c478bd9Sstevel@tonic-gate {
959*7c478bd9Sstevel@tonic-gate 	char	*tok = NULL;
960*7c478bd9Sstevel@tonic-gate 	char	*tnametok = NULL;
961*7c478bd9Sstevel@tonic-gate 	char	*last = NULL;
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate 	/* get the TABLE directive */
964*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
965*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
966*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
967*7c478bd9Sstevel@tonic-gate 
968*7c478bd9Sstevel@tonic-gate 	/* get the property name */
969*7c478bd9Sstevel@tonic-gate 	tnametok = strtok_r(last, WHITESPACE, &last);
970*7c478bd9Sstevel@tonic-gate 	if (tnametok == NULL)
971*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate 	command->tablecmd_tname = strdup(tnametok);
974*7c478bd9Sstevel@tonic-gate 	if (command->tablecmd_tname == NULL)
975*7c478bd9Sstevel@tonic-gate 		return (EC_FAILURE);
976*7c478bd9Sstevel@tonic-gate 
977*7c478bd9Sstevel@tonic-gate 	command->tablecmd_newtbl = 0;
978*7c478bd9Sstevel@tonic-gate 	command->tablecmd_tblh = NULL;
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
981*7c478bd9Sstevel@tonic-gate }
982*7c478bd9Sstevel@tonic-gate 
983*7c478bd9Sstevel@tonic-gate /*
984*7c478bd9Sstevel@tonic-gate  * Process the TABLE command and add the specified property under the given
985*7c478bd9Sstevel@tonic-gate  * node handle
986*7c478bd9Sstevel@tonic-gate  */
987*7c478bd9Sstevel@tonic-gate static int
988*7c478bd9Sstevel@tonic-gate process_table(command_t *command, picl_nodehdl_t nodeh)
989*7c478bd9Sstevel@tonic-gate {
990*7c478bd9Sstevel@tonic-gate 	int			err;
991*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t 		tblh;
992*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t 		proph;
993*7c478bd9Sstevel@tonic-gate 	ptree_propinfo_t	propinfo;
994*7c478bd9Sstevel@tonic-gate 
995*7c478bd9Sstevel@tonic-gate 	/* find if table already exists */
996*7c478bd9Sstevel@tonic-gate 	err = ptree_get_prop_by_name(nodeh, command->tablecmd_tname, &tblh);
997*7c478bd9Sstevel@tonic-gate 	if (err == PICL_SUCCESS) {
998*7c478bd9Sstevel@tonic-gate 		err = ptree_get_propinfo(tblh, &propinfo);
999*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
1000*7c478bd9Sstevel@tonic-gate 			return (err);
1001*7c478bd9Sstevel@tonic-gate 		/* prop with the same name as table? */
1002*7c478bd9Sstevel@tonic-gate 		if (propinfo.piclinfo.type != PICL_PTYPE_TABLE)
1003*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1004*7c478bd9Sstevel@tonic-gate 		command->tablecmd_newtbl = 0;
1005*7c478bd9Sstevel@tonic-gate 		command->tablecmd_tblh = tblh;
1006*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
1007*7c478bd9Sstevel@tonic-gate 	}
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 	/* init and create a new table */
1010*7c478bd9Sstevel@tonic-gate 	err = ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
1011*7c478bd9Sstevel@tonic-gate 		PICL_PTYPE_TABLE, PICL_READ|PICL_WRITE,
1012*7c478bd9Sstevel@tonic-gate 		sizeof (picl_prophdl_t), command->tablecmd_tname, NULL, NULL);
1013*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1014*7c478bd9Sstevel@tonic-gate 		return (err);
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate 	err = ptree_create_table(&tblh);
1017*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1018*7c478bd9Sstevel@tonic-gate 		return (err);
1019*7c478bd9Sstevel@tonic-gate 
1020*7c478bd9Sstevel@tonic-gate 	command->tablecmd_newtbl = 1;
1021*7c478bd9Sstevel@tonic-gate 	command->tablecmd_tblh = tblh;
1022*7c478bd9Sstevel@tonic-gate 
1023*7c478bd9Sstevel@tonic-gate 	err = ptree_create_prop(&propinfo, &tblh, &proph);
1024*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS)
1025*7c478bd9Sstevel@tonic-gate 		return (err);
1026*7c478bd9Sstevel@tonic-gate 
1027*7c478bd9Sstevel@tonic-gate 	err = ptree_add_prop(nodeh, proph);
1028*7c478bd9Sstevel@tonic-gate 
1029*7c478bd9Sstevel@tonic-gate 	return (err);
1030*7c478bd9Sstevel@tonic-gate }
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate /*
1033*7c478bd9Sstevel@tonic-gate  * Process the ROW command by alloc'ing space to store the prop handles for
1034*7c478bd9Sstevel@tonic-gate  * the whole row. The number of props in the row gets known while parsing.
1035*7c478bd9Sstevel@tonic-gate  */
1036*7c478bd9Sstevel@tonic-gate static int
1037*7c478bd9Sstevel@tonic-gate process_row(command_t *command)
1038*7c478bd9Sstevel@tonic-gate {
1039*7c478bd9Sstevel@tonic-gate 	command->rowcmd_index = 0;
1040*7c478bd9Sstevel@tonic-gate 	command->rowcmd_prophs =
1041*7c478bd9Sstevel@tonic-gate 		malloc(command->rowcmd_nproph * sizeof (picl_prophdl_t));
1042*7c478bd9Sstevel@tonic-gate 
1043*7c478bd9Sstevel@tonic-gate 	if (command->rowcmd_prophs == NULL)
1044*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1047*7c478bd9Sstevel@tonic-gate }
1048*7c478bd9Sstevel@tonic-gate 
1049*7c478bd9Sstevel@tonic-gate /*
1050*7c478bd9Sstevel@tonic-gate  * Process the ENDROW command. If a valid row, add the row to the ptree.
1051*7c478bd9Sstevel@tonic-gate  */
1052*7c478bd9Sstevel@tonic-gate static int
1053*7c478bd9Sstevel@tonic-gate process_endrow(cmdbuf_t *cmds)
1054*7c478bd9Sstevel@tonic-gate {
1055*7c478bd9Sstevel@tonic-gate 	int		err;
1056*7c478bd9Sstevel@tonic-gate 	int		i;
1057*7c478bd9Sstevel@tonic-gate 	command_t	*curr_row;
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 	curr_row = &cmds->commands[cmds->current_row];
1060*7c478bd9Sstevel@tonic-gate 
1061*7c478bd9Sstevel@tonic-gate 	/* if nproph == 0, some row prop had problems, don't add  */
1062*7c478bd9Sstevel@tonic-gate 	if (curr_row->rowcmd_nproph == 0) {
1063*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < curr_row->rowcmd_index; i++) {
1064*7c478bd9Sstevel@tonic-gate 			(void) ptree_delete_prop(curr_row->rowcmd_prophs[i]);
1065*7c478bd9Sstevel@tonic-gate 			(void) ptree_destroy_prop(curr_row->rowcmd_prophs[i]);
1066*7c478bd9Sstevel@tonic-gate 		}
1067*7c478bd9Sstevel@tonic-gate 		err = PICL_SUCCESS;
1068*7c478bd9Sstevel@tonic-gate 	} else
1069*7c478bd9Sstevel@tonic-gate 		err = ptree_add_row_to_table(
1070*7c478bd9Sstevel@tonic-gate 			cmds->commands[cmds->current_tbl].tablecmd_tblh,
1071*7c478bd9Sstevel@tonic-gate 			curr_row->rowcmd_nproph,
1072*7c478bd9Sstevel@tonic-gate 			curr_row->rowcmd_prophs);
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 	/* let go the space alloc'd in process_row */
1075*7c478bd9Sstevel@tonic-gate 	free(curr_row->rowcmd_prophs);
1076*7c478bd9Sstevel@tonic-gate 	curr_row->rowcmd_prophs = NULL;
1077*7c478bd9Sstevel@tonic-gate 
1078*7c478bd9Sstevel@tonic-gate 	return (err);
1079*7c478bd9Sstevel@tonic-gate }
1080*7c478bd9Sstevel@tonic-gate 
1081*7c478bd9Sstevel@tonic-gate /*
1082*7c478bd9Sstevel@tonic-gate  * Check the VERBOSE syntax
1083*7c478bd9Sstevel@tonic-gate  * VERBOSE <level>
1084*7c478bd9Sstevel@tonic-gate  */
1085*7c478bd9Sstevel@tonic-gate static int
1086*7c478bd9Sstevel@tonic-gate parse_verbose(cmdbuf_t *cmds, char *line, command_t *command)
1087*7c478bd9Sstevel@tonic-gate {
1088*7c478bd9Sstevel@tonic-gate 	char	*tok;
1089*7c478bd9Sstevel@tonic-gate 	char	*level;
1090*7c478bd9Sstevel@tonic-gate 	char	*last;
1091*7c478bd9Sstevel@tonic-gate 	char	*endptr;
1092*7c478bd9Sstevel@tonic-gate 	int	verbose_level;
1093*7c478bd9Sstevel@tonic-gate 
1094*7c478bd9Sstevel@tonic-gate 	/* get the VERBOSE directive */
1095*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(line, WHITESPACE, &last);
1096*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
1097*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
1098*7c478bd9Sstevel@tonic-gate 
1099*7c478bd9Sstevel@tonic-gate 	/* get verbose level */
1100*7c478bd9Sstevel@tonic-gate 	level = strtok_r(last, WHITESPACE, &last);
1101*7c478bd9Sstevel@tonic-gate 	if (level == NULL)
1102*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
1103*7c478bd9Sstevel@tonic-gate 	verbose_level = strtol(level, &endptr, 0);
1104*7c478bd9Sstevel@tonic-gate 	if (endptr != (level + strlen(level)))
1105*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate 	/* check if more tokens */
1108*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(last, WHITESPACE, &last);
1109*7c478bd9Sstevel@tonic-gate 	if (tok != NULL)
1110*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
1111*7c478bd9Sstevel@tonic-gate 
1112*7c478bd9Sstevel@tonic-gate 	cmds->verbose = verbose_level;
1113*7c478bd9Sstevel@tonic-gate 	command->verbosecmd_level = verbose_level;
1114*7c478bd9Sstevel@tonic-gate 
1115*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
1116*7c478bd9Sstevel@tonic-gate }
1117*7c478bd9Sstevel@tonic-gate 
1118*7c478bd9Sstevel@tonic-gate /*
1119*7c478bd9Sstevel@tonic-gate  * Process the VERBOSE command to set the verbose level
1120*7c478bd9Sstevel@tonic-gate  */
1121*7c478bd9Sstevel@tonic-gate static int
1122*7c478bd9Sstevel@tonic-gate process_verbose(cmdbuf_t *cmds, command_t *command)
1123*7c478bd9Sstevel@tonic-gate {
1124*7c478bd9Sstevel@tonic-gate 	cmds->verbose = command->verbosecmd_level;
1125*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1126*7c478bd9Sstevel@tonic-gate }
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate /*
1129*7c478bd9Sstevel@tonic-gate  * parse and tokenize the line
1130*7c478bd9Sstevel@tonic-gate  */
1131*7c478bd9Sstevel@tonic-gate static int
1132*7c478bd9Sstevel@tonic-gate parse_and_tokenize_line(cmdbuf_t *cmds, char *buf, command_t *command)
1133*7c478bd9Sstevel@tonic-gate {
1134*7c478bd9Sstevel@tonic-gate 	char		rec[RECORD_SIZE_MAX];
1135*7c478bd9Sstevel@tonic-gate 	char		*tok;
1136*7c478bd9Sstevel@tonic-gate 	int		err;
1137*7c478bd9Sstevel@tonic-gate 	char		*last;
1138*7c478bd9Sstevel@tonic-gate 	int		id;
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate 	(void) strcpy(rec, buf);
1141*7c478bd9Sstevel@tonic-gate 	tok = strtok_r(rec, RECORD_WHITESPACE, &last);
1142*7c478bd9Sstevel@tonic-gate 	if (tok == NULL)
1143*7c478bd9Sstevel@tonic-gate 		return (EC_INSUFFICIENT_TOKEN);
1144*7c478bd9Sstevel@tonic-gate 
1145*7c478bd9Sstevel@tonic-gate 	id = get_token_id(tok);
1146*7c478bd9Sstevel@tonic-gate 
1147*7c478bd9Sstevel@tonic-gate 	(void) strcpy(rec, buf);
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate 	switch (id) {
1150*7c478bd9Sstevel@tonic-gate 	case TOK_VERSION:
1151*7c478bd9Sstevel@tonic-gate 		err = parse_version(cmds, rec);
1152*7c478bd9Sstevel@tonic-gate 		break;
1153*7c478bd9Sstevel@tonic-gate 	case TOK_CLASSPATH:
1154*7c478bd9Sstevel@tonic-gate 	case TOK_NAMEPATH:
1155*7c478bd9Sstevel@tonic-gate 		if (cmds->inside_node_block != 0)
1156*7c478bd9Sstevel@tonic-gate 			return (EC_PATH_ERR);
1157*7c478bd9Sstevel@tonic-gate 
1158*7c478bd9Sstevel@tonic-gate 		err = parse_path(rec, command);
1159*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1160*7c478bd9Sstevel@tonic-gate 			return (err);
1161*7c478bd9Sstevel@tonic-gate 		break;
1162*7c478bd9Sstevel@tonic-gate 	case TOK_NODE:
1163*7c478bd9Sstevel@tonic-gate 		/* Check for NODE outside of TABLE, ROW */
1164*7c478bd9Sstevel@tonic-gate 		if ((cmds->inside_table_block != 0) ||
1165*7c478bd9Sstevel@tonic-gate 		    (cmds->inside_row_block != 0))
1166*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1167*7c478bd9Sstevel@tonic-gate 		err = parse_node(rec, command);
1168*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1169*7c478bd9Sstevel@tonic-gate 			return (err);
1170*7c478bd9Sstevel@tonic-gate 		cmds->inside_node_block++;
1171*7c478bd9Sstevel@tonic-gate 		break;
1172*7c478bd9Sstevel@tonic-gate 	case TOK_ENDNODE:
1173*7c478bd9Sstevel@tonic-gate 		/* Check for ENDNODE outside of TABLE, ROW */
1174*7c478bd9Sstevel@tonic-gate 		if ((cmds->inside_table_block != 0) ||
1175*7c478bd9Sstevel@tonic-gate 		    (cmds->inside_row_block != 0))
1176*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1177*7c478bd9Sstevel@tonic-gate 		cmds->inside_node_block--;
1178*7c478bd9Sstevel@tonic-gate 		err = EC_SYNTAX_OK;
1179*7c478bd9Sstevel@tonic-gate 		break;
1180*7c478bd9Sstevel@tonic-gate 	case TOK_PROP:
1181*7c478bd9Sstevel@tonic-gate 		/* Check if inside TABLE, but not in ROW */
1182*7c478bd9Sstevel@tonic-gate 		if ((cmds->inside_table_block != 0) &&
1183*7c478bd9Sstevel@tonic-gate 		    (cmds->inside_row_block == 0))
1184*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1185*7c478bd9Sstevel@tonic-gate 		err = parse_prop(rec, command);
1186*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1187*7c478bd9Sstevel@tonic-gate 			return (err);
1188*7c478bd9Sstevel@tonic-gate 		if (cmds->inside_row_block) {
1189*7c478bd9Sstevel@tonic-gate 			cmds->commands[cmds->current_row].rowcmd_nproph++;
1190*7c478bd9Sstevel@tonic-gate 		}
1191*7c478bd9Sstevel@tonic-gate 		break;
1192*7c478bd9Sstevel@tonic-gate 	case TOK_REFNODE:
1193*7c478bd9Sstevel@tonic-gate 		err = parse_refnode(rec, command);
1194*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1195*7c478bd9Sstevel@tonic-gate 			return (err);
1196*7c478bd9Sstevel@tonic-gate 		break;
1197*7c478bd9Sstevel@tonic-gate 	case TOK_REFPROP:
1198*7c478bd9Sstevel@tonic-gate 		/* Check if inside TABLE, but not in ROW */
1199*7c478bd9Sstevel@tonic-gate 		if ((cmds->inside_table_block != 0) &&
1200*7c478bd9Sstevel@tonic-gate 		    (cmds->inside_row_block == 0))
1201*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1202*7c478bd9Sstevel@tonic-gate 		err = parse_refprop(rec, command);
1203*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1204*7c478bd9Sstevel@tonic-gate 			return (err);
1205*7c478bd9Sstevel@tonic-gate 		if (cmds->inside_row_block) {
1206*7c478bd9Sstevel@tonic-gate 			cmds->commands[cmds->current_row].rowcmd_nproph++;
1207*7c478bd9Sstevel@tonic-gate 		}
1208*7c478bd9Sstevel@tonic-gate 		break;
1209*7c478bd9Sstevel@tonic-gate 	case TOK_TABLE:
1210*7c478bd9Sstevel@tonic-gate 		/* Table/Row supported in version 1.1 and above */
1211*7c478bd9Sstevel@tonic-gate 		if (cmds->version_no < (float)SUPPORTED_VERSION_NUM)
1212*7c478bd9Sstevel@tonic-gate 			return (EC_UNSUPPORTED);
1213*7c478bd9Sstevel@tonic-gate 		if (cmds->inside_table_block != 0)
1214*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1215*7c478bd9Sstevel@tonic-gate 		err = parse_table(rec, command);
1216*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1217*7c478bd9Sstevel@tonic-gate 			return (err);
1218*7c478bd9Sstevel@tonic-gate 		cmds->inside_table_block = 1;
1219*7c478bd9Sstevel@tonic-gate 		break;
1220*7c478bd9Sstevel@tonic-gate 	case TOK_ENDTABLE:
1221*7c478bd9Sstevel@tonic-gate 		/* Check for ENDTABLE before TABLE */
1222*7c478bd9Sstevel@tonic-gate 		if (cmds->inside_table_block == 0)
1223*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1224*7c478bd9Sstevel@tonic-gate 
1225*7c478bd9Sstevel@tonic-gate 		cmds->inside_table_block = 0;
1226*7c478bd9Sstevel@tonic-gate 
1227*7c478bd9Sstevel@tonic-gate 		break;
1228*7c478bd9Sstevel@tonic-gate 	case TOK_ROW:
1229*7c478bd9Sstevel@tonic-gate 		/* Check for ROW outside of TABLE, ROW inside ROW */
1230*7c478bd9Sstevel@tonic-gate 		if ((cmds->inside_table_block == 0) ||
1231*7c478bd9Sstevel@tonic-gate 		    (cmds->inside_row_block != 0))
1232*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1233*7c478bd9Sstevel@tonic-gate 		cmds->inside_row_block = 1;
1234*7c478bd9Sstevel@tonic-gate 		break;
1235*7c478bd9Sstevel@tonic-gate 	case TOK_ENDROW:
1236*7c478bd9Sstevel@tonic-gate 		/* Check for ENDROW outside of TABLE, ENDROW before ROW */
1237*7c478bd9Sstevel@tonic-gate 		if ((cmds->inside_table_block == 0) ||
1238*7c478bd9Sstevel@tonic-gate 		    (cmds->inside_row_block == 0))
1239*7c478bd9Sstevel@tonic-gate 			return (EC_SYNTAX_ERR);
1240*7c478bd9Sstevel@tonic-gate 		else
1241*7c478bd9Sstevel@tonic-gate 			err = EC_SYNTAX_OK;
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate 		cmds->inside_row_block = 0;
1244*7c478bd9Sstevel@tonic-gate 
1245*7c478bd9Sstevel@tonic-gate 		/* error if row is empty */
1246*7c478bd9Sstevel@tonic-gate 		if (cmds->commands[cmds->current_row].rowcmd_nproph <= 0)
1247*7c478bd9Sstevel@tonic-gate 			return (EC_ROW_EMPTY);
1248*7c478bd9Sstevel@tonic-gate 		break;
1249*7c478bd9Sstevel@tonic-gate 	case TOK_VERBOSE:
1250*7c478bd9Sstevel@tonic-gate 		err = parse_verbose(cmds, rec, command);
1251*7c478bd9Sstevel@tonic-gate 		if (err != EC_SYNTAX_OK)
1252*7c478bd9Sstevel@tonic-gate 			return (err);
1253*7c478bd9Sstevel@tonic-gate 		break;
1254*7c478bd9Sstevel@tonic-gate 	default:	/* unsupported command */
1255*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_ERR);
1256*7c478bd9Sstevel@tonic-gate 	}
1257*7c478bd9Sstevel@tonic-gate 
1258*7c478bd9Sstevel@tonic-gate 	command->type = id;
1259*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
1260*7c478bd9Sstevel@tonic-gate }
1261*7c478bd9Sstevel@tonic-gate 
1262*7c478bd9Sstevel@tonic-gate /*
1263*7c478bd9Sstevel@tonic-gate  * Check the syntax and save the tokens in the commands buffer
1264*7c478bd9Sstevel@tonic-gate  */
1265*7c478bd9Sstevel@tonic-gate static int
1266*7c478bd9Sstevel@tonic-gate check_line_syntax(cmdbuf_t *cmds, char *buf)
1267*7c478bd9Sstevel@tonic-gate {
1268*7c478bd9Sstevel@tonic-gate 	int		err;
1269*7c478bd9Sstevel@tonic-gate 	command_t	command;
1270*7c478bd9Sstevel@tonic-gate 
1271*7c478bd9Sstevel@tonic-gate 	(void) memset(&command, 0, sizeof (command_t));
1272*7c478bd9Sstevel@tonic-gate 	err = parse_and_tokenize_line(cmds, buf, &command);
1273*7c478bd9Sstevel@tonic-gate 	if (err != EC_SYNTAX_OK)
1274*7c478bd9Sstevel@tonic-gate 		return (err);
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate 	/*
1277*7c478bd9Sstevel@tonic-gate 	 * don't add and count version command in the command buffer
1278*7c478bd9Sstevel@tonic-gate 	 */
1279*7c478bd9Sstevel@tonic-gate 	if (command.type == TOK_VERSION)
1280*7c478bd9Sstevel@tonic-gate 		return (EC_SYNTAX_OK);
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate 	/*
1283*7c478bd9Sstevel@tonic-gate 	 * check if the commands buffer has been filled
1284*7c478bd9Sstevel@tonic-gate 	 * If it is full, reallocate the buffer.
1285*7c478bd9Sstevel@tonic-gate 	 */
1286*7c478bd9Sstevel@tonic-gate 	if (cmds->count == cmds->allocated) {
1287*7c478bd9Sstevel@tonic-gate 		cmds->commands = realloc(cmds->commands,
1288*7c478bd9Sstevel@tonic-gate 		    sizeof (command_t) * (cmds->allocated + PER_ALLOC_COUNT));
1289*7c478bd9Sstevel@tonic-gate 		if (cmds->commands == NULL)
1290*7c478bd9Sstevel@tonic-gate 			return (EC_FAILURE);
1291*7c478bd9Sstevel@tonic-gate 		cmds->allocated += PER_ALLOC_COUNT;
1292*7c478bd9Sstevel@tonic-gate 	}
1293*7c478bd9Sstevel@tonic-gate 
1294*7c478bd9Sstevel@tonic-gate 	cmds->commands[cmds->count] = command;	/* copy */
1295*7c478bd9Sstevel@tonic-gate 
1296*7c478bd9Sstevel@tonic-gate 	/*
1297*7c478bd9Sstevel@tonic-gate 	 * make a note of the row/endrow command, to keep track of # of props
1298*7c478bd9Sstevel@tonic-gate 	 */
1299*7c478bd9Sstevel@tonic-gate 	if (command.type == TOK_ROW)
1300*7c478bd9Sstevel@tonic-gate 		cmds->current_row = cmds->count;
1301*7c478bd9Sstevel@tonic-gate 
1302*7c478bd9Sstevel@tonic-gate 	if (command.type == TOK_ENDROW)
1303*7c478bd9Sstevel@tonic-gate 		cmds->current_row = 0;
1304*7c478bd9Sstevel@tonic-gate 
1305*7c478bd9Sstevel@tonic-gate 	cmds->count++;
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
1308*7c478bd9Sstevel@tonic-gate }
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate /*
1311*7c478bd9Sstevel@tonic-gate  * get the line control information
1312*7c478bd9Sstevel@tonic-gate  * return 1 if it's the line control information, else return 0
1313*7c478bd9Sstevel@tonic-gate  */
1314*7c478bd9Sstevel@tonic-gate static int
1315*7c478bd9Sstevel@tonic-gate get_line_control_info(char *buf, uint32_t *linenum, char *filename)
1316*7c478bd9Sstevel@tonic-gate {
1317*7c478bd9Sstevel@tonic-gate 	char		*ptr;
1318*7c478bd9Sstevel@tonic-gate 	char		*last;
1319*7c478bd9Sstevel@tonic-gate 	uint32_t	num;
1320*7c478bd9Sstevel@tonic-gate 	char		*fname;
1321*7c478bd9Sstevel@tonic-gate 	char		*endptr;
1322*7c478bd9Sstevel@tonic-gate 
1323*7c478bd9Sstevel@tonic-gate 	/* skip # and get next string */
1324*7c478bd9Sstevel@tonic-gate 	ptr = strtok_r(buf + 1, WHITESPACE, &last);
1325*7c478bd9Sstevel@tonic-gate 	if (ptr == NULL) {
1326*7c478bd9Sstevel@tonic-gate 		return (0);
1327*7c478bd9Sstevel@tonic-gate 	}
1328*7c478bd9Sstevel@tonic-gate 
1329*7c478bd9Sstevel@tonic-gate 	num = strtoul(ptr, &endptr, 0);
1330*7c478bd9Sstevel@tonic-gate 
1331*7c478bd9Sstevel@tonic-gate 	/*
1332*7c478bd9Sstevel@tonic-gate 	 * It's not the line control information
1333*7c478bd9Sstevel@tonic-gate 	 */
1334*7c478bd9Sstevel@tonic-gate 	if (endptr != (ptr + strlen(ptr))) {
1335*7c478bd9Sstevel@tonic-gate 		return (0);
1336*7c478bd9Sstevel@tonic-gate 	}
1337*7c478bd9Sstevel@tonic-gate 
1338*7c478bd9Sstevel@tonic-gate 	/*
1339*7c478bd9Sstevel@tonic-gate 	 * get the filename
1340*7c478bd9Sstevel@tonic-gate 	 */
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate 	/* get the beginning double quote */
1343*7c478bd9Sstevel@tonic-gate 	last = strchr(last, '"');
1344*7c478bd9Sstevel@tonic-gate 	if (last == NULL)
1345*7c478bd9Sstevel@tonic-gate 		return (0);
1346*7c478bd9Sstevel@tonic-gate 
1347*7c478bd9Sstevel@tonic-gate 	last++;
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 	/* get the ending double quote */
1350*7c478bd9Sstevel@tonic-gate 	fname = strtok_r(last, DOUBLE_QUOTE, &last);
1351*7c478bd9Sstevel@tonic-gate 	if (fname == NULL)
1352*7c478bd9Sstevel@tonic-gate 		return (0);
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 	*linenum = num;
1355*7c478bd9Sstevel@tonic-gate 	(void) strlcpy(filename, fname, PATH_MAX);
1356*7c478bd9Sstevel@tonic-gate 	return (1);
1357*7c478bd9Sstevel@tonic-gate }
1358*7c478bd9Sstevel@tonic-gate 
1359*7c478bd9Sstevel@tonic-gate /*
1360*7c478bd9Sstevel@tonic-gate  * check the syntax of the configuration file
1361*7c478bd9Sstevel@tonic-gate  */
1362*7c478bd9Sstevel@tonic-gate static int
1363*7c478bd9Sstevel@tonic-gate check_conffile_syntax(cmdbuf_t *cmds, FILE *fp)
1364*7c478bd9Sstevel@tonic-gate {
1365*7c478bd9Sstevel@tonic-gate 	char		lbuf[RECORD_SIZE_MAX];
1366*7c478bd9Sstevel@tonic-gate 	char		buf[RECORD_SIZE_MAX];
1367*7c478bd9Sstevel@tonic-gate 	uint32_t	linenum;
1368*7c478bd9Sstevel@tonic-gate 	char		cppfile[PATH_MAX] = "";
1369*7c478bd9Sstevel@tonic-gate 	int		err = EC_SYNTAX_OK;
1370*7c478bd9Sstevel@tonic-gate 
1371*7c478bd9Sstevel@tonic-gate 	linenum = 0;
1372*7c478bd9Sstevel@tonic-gate 	while (fgets(buf, sizeof (buf), fp) != NULL) {
1373*7c478bd9Sstevel@tonic-gate 		/*
1374*7c478bd9Sstevel@tonic-gate 		 * get cpp line control information, if any
1375*7c478bd9Sstevel@tonic-gate 		 */
1376*7c478bd9Sstevel@tonic-gate 		if (buf[0] == '#') {
1377*7c478bd9Sstevel@tonic-gate 			if (!get_line_control_info(buf, &linenum, cppfile))
1378*7c478bd9Sstevel@tonic-gate 				++linenum;
1379*7c478bd9Sstevel@tonic-gate 			continue;
1380*7c478bd9Sstevel@tonic-gate 		}
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 		++linenum;
1383*7c478bd9Sstevel@tonic-gate 		/*
1384*7c478bd9Sstevel@tonic-gate 		 * skip line whose first char is a newline char
1385*7c478bd9Sstevel@tonic-gate 		 */
1386*7c478bd9Sstevel@tonic-gate 		if (buf[0] == '\n') {
1387*7c478bd9Sstevel@tonic-gate 			continue;
1388*7c478bd9Sstevel@tonic-gate 		}
1389*7c478bd9Sstevel@tonic-gate 
1390*7c478bd9Sstevel@tonic-gate 		if (err == EC_SYNTAX_OK)
1391*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(lbuf, buf, RECORD_SIZE_MAX);
1392*7c478bd9Sstevel@tonic-gate 		else if (strlcat(lbuf, buf, RECORD_SIZE_MAX) >=
1393*7c478bd9Sstevel@tonic-gate 		    RECORD_SIZE_MAX) { 	/* buffer overflow */
1394*7c478bd9Sstevel@tonic-gate 			err = EC_FAILURE;
1395*7c478bd9Sstevel@tonic-gate 			break;
1396*7c478bd9Sstevel@tonic-gate 		}
1397*7c478bd9Sstevel@tonic-gate 
1398*7c478bd9Sstevel@tonic-gate 		err = check_line_syntax(cmds, lbuf);
1399*7c478bd9Sstevel@tonic-gate 		if ((err != EC_INSUFFICIENT_TOKEN) && (err != EC_SYNTAX_OK))
1400*7c478bd9Sstevel@tonic-gate 			break;
1401*7c478bd9Sstevel@tonic-gate 	}
1402*7c478bd9Sstevel@tonic-gate 
1403*7c478bd9Sstevel@tonic-gate 	if (err != EC_SYNTAX_OK) {
1404*7c478bd9Sstevel@tonic-gate 		if (cmds->verbose) {
1405*7c478bd9Sstevel@tonic-gate 			verbose_log(LOG_ERR, err_msg[err],
1406*7c478bd9Sstevel@tonic-gate 			    cmds->fname, cppfile, linenum);
1407*7c478bd9Sstevel@tonic-gate 		}
1408*7c478bd9Sstevel@tonic-gate 		return (err);
1409*7c478bd9Sstevel@tonic-gate 	}
1410*7c478bd9Sstevel@tonic-gate 
1411*7c478bd9Sstevel@tonic-gate 	/*
1412*7c478bd9Sstevel@tonic-gate 	 * check if the version has been set
1413*7c478bd9Sstevel@tonic-gate 	 */
1414*7c478bd9Sstevel@tonic-gate 	if (cmds->version_no > (float)SUPPORTED_VERSION_NUM) {
1415*7c478bd9Sstevel@tonic-gate 		if (cmds->verbose) {
1416*7c478bd9Sstevel@tonic-gate 			verbose_log(LOG_ERR, err_msg[EC_UNSUPPORTED],
1417*7c478bd9Sstevel@tonic-gate 			    cmds->fname, cppfile, linenum);
1418*7c478bd9Sstevel@tonic-gate 		}
1419*7c478bd9Sstevel@tonic-gate 		return (EC_UNSUPPORTED);
1420*7c478bd9Sstevel@tonic-gate 	}
1421*7c478bd9Sstevel@tonic-gate 
1422*7c478bd9Sstevel@tonic-gate 	/*
1423*7c478bd9Sstevel@tonic-gate 	 * check if node and endnode command mismatch
1424*7c478bd9Sstevel@tonic-gate 	 */
1425*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_node_block != 0) {
1426*7c478bd9Sstevel@tonic-gate 		if (cmds->verbose) {
1427*7c478bd9Sstevel@tonic-gate 			verbose_log(LOG_ERR, err_msg[EC_NODE_MISMATCH],
1428*7c478bd9Sstevel@tonic-gate 			    cmds->fname, cppfile, linenum);
1429*7c478bd9Sstevel@tonic-gate 		}
1430*7c478bd9Sstevel@tonic-gate 		return (EC_NODE_MISMATCH);
1431*7c478bd9Sstevel@tonic-gate 	}
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 	/*
1434*7c478bd9Sstevel@tonic-gate 	 * check if row and endrow command mismatch
1435*7c478bd9Sstevel@tonic-gate 	 */
1436*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_row_block != 0) {
1437*7c478bd9Sstevel@tonic-gate 		if (cmds->verbose) {
1438*7c478bd9Sstevel@tonic-gate 			verbose_log(LOG_ERR, err_msg[EC_ROW_MISMATCH],
1439*7c478bd9Sstevel@tonic-gate 			    cmds->fname, cppfile, linenum);
1440*7c478bd9Sstevel@tonic-gate 		}
1441*7c478bd9Sstevel@tonic-gate 		return (EC_ROW_MISMATCH);
1442*7c478bd9Sstevel@tonic-gate 	}
1443*7c478bd9Sstevel@tonic-gate 
1444*7c478bd9Sstevel@tonic-gate 	/*
1445*7c478bd9Sstevel@tonic-gate 	 * check if table and endtable command mismatch
1446*7c478bd9Sstevel@tonic-gate 	 */
1447*7c478bd9Sstevel@tonic-gate 	if (cmds->inside_table_block != 0) {
1448*7c478bd9Sstevel@tonic-gate 		if (cmds->verbose) {
1449*7c478bd9Sstevel@tonic-gate 			verbose_log(LOG_ERR, err_msg[EC_TABLE_MISMATCH],
1450*7c478bd9Sstevel@tonic-gate 			    cmds->fname, cppfile, linenum);
1451*7c478bd9Sstevel@tonic-gate 		}
1452*7c478bd9Sstevel@tonic-gate 		return (EC_TABLE_MISMATCH);
1453*7c478bd9Sstevel@tonic-gate 	}
1454*7c478bd9Sstevel@tonic-gate 
1455*7c478bd9Sstevel@tonic-gate 	return (EC_SYNTAX_OK);
1456*7c478bd9Sstevel@tonic-gate }
1457*7c478bd9Sstevel@tonic-gate 
1458*7c478bd9Sstevel@tonic-gate /*
1459*7c478bd9Sstevel@tonic-gate  * If classpath/namepath given is not found in the picl tree,
1460*7c478bd9Sstevel@tonic-gate  * skip the whole blocks until next valid classpath or namepath
1461*7c478bd9Sstevel@tonic-gate  */
1462*7c478bd9Sstevel@tonic-gate static void
1463*7c478bd9Sstevel@tonic-gate skip_to_next_valid_path(cmdbuf_t *cmds, int starting_index,
1464*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t *parent, int *last_processed_index)
1465*7c478bd9Sstevel@tonic-gate {
1466*7c478bd9Sstevel@tonic-gate 	int	err;
1467*7c478bd9Sstevel@tonic-gate 	int	index;
1468*7c478bd9Sstevel@tonic-gate 
1469*7c478bd9Sstevel@tonic-gate 	for (index = starting_index; index < cmds->count; ++index) {
1470*7c478bd9Sstevel@tonic-gate 		switch (cmds->commands[index].type) {
1471*7c478bd9Sstevel@tonic-gate 		    case TOK_CLASSPATH:
1472*7c478bd9Sstevel@tonic-gate 		    case TOK_NAMEPATH:
1473*7c478bd9Sstevel@tonic-gate 			err = process_path(&cmds->commands[index], parent);
1474*7c478bd9Sstevel@tonic-gate 			if (err == PICL_SUCCESS) {
1475*7c478bd9Sstevel@tonic-gate 				*last_processed_index = index;
1476*7c478bd9Sstevel@tonic-gate 				return;
1477*7c478bd9Sstevel@tonic-gate 			}
1478*7c478bd9Sstevel@tonic-gate 		    default:
1479*7c478bd9Sstevel@tonic-gate 			/* skipped this line */
1480*7c478bd9Sstevel@tonic-gate 			break;
1481*7c478bd9Sstevel@tonic-gate 		}
1482*7c478bd9Sstevel@tonic-gate 	}
1483*7c478bd9Sstevel@tonic-gate 
1484*7c478bd9Sstevel@tonic-gate 	/* reach last command  */
1485*7c478bd9Sstevel@tonic-gate 	*last_processed_index = cmds->count - 1;
1486*7c478bd9Sstevel@tonic-gate }
1487*7c478bd9Sstevel@tonic-gate 
1488*7c478bd9Sstevel@tonic-gate /*
1489*7c478bd9Sstevel@tonic-gate  * Process the command buffer and return last command index and the new head of
1490*7c478bd9Sstevel@tonic-gate  * the handle list
1491*7c478bd9Sstevel@tonic-gate  */
1492*7c478bd9Sstevel@tonic-gate static int
1493*7c478bd9Sstevel@tonic-gate process_commands(cmdbuf_t *cmds, int starting_index, picl_nodehdl_t parent,
1494*7c478bd9Sstevel@tonic-gate     int *last_processed_index)
1495*7c478bd9Sstevel@tonic-gate {
1496*7c478bd9Sstevel@tonic-gate 	int		err;
1497*7c478bd9Sstevel@tonic-gate 	int		index;
1498*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	rooth;
1499*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	nodeh;
1500*7c478bd9Sstevel@tonic-gate 	command_t	*commands = cmds->commands;
1501*7c478bd9Sstevel@tonic-gate 
1502*7c478bd9Sstevel@tonic-gate 	for (index = starting_index; index < cmds->count; ++index) {
1503*7c478bd9Sstevel@tonic-gate 		switch (commands[index].type) {
1504*7c478bd9Sstevel@tonic-gate 		case TOK_CLASSPATH:
1505*7c478bd9Sstevel@tonic-gate 		case TOK_NAMEPATH:
1506*7c478bd9Sstevel@tonic-gate 			err = process_path(&commands[index], &rooth);
1507*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
1508*7c478bd9Sstevel@tonic-gate 				index++;
1509*7c478bd9Sstevel@tonic-gate 				(void) skip_to_next_valid_path(cmds, index,
1510*7c478bd9Sstevel@tonic-gate 				    &rooth, &index);
1511*7c478bd9Sstevel@tonic-gate 			}
1512*7c478bd9Sstevel@tonic-gate 			parent = rooth;
1513*7c478bd9Sstevel@tonic-gate 			continue;
1514*7c478bd9Sstevel@tonic-gate 		case TOK_NODE:
1515*7c478bd9Sstevel@tonic-gate 			err = process_node(&commands[index], parent, &nodeh);
1516*7c478bd9Sstevel@tonic-gate 			if (err == PICL_SUCCESS) {
1517*7c478bd9Sstevel@tonic-gate 				index++;
1518*7c478bd9Sstevel@tonic-gate 				err = process_commands(cmds, index, nodeh,
1519*7c478bd9Sstevel@tonic-gate 				    &index);
1520*7c478bd9Sstevel@tonic-gate 			}
1521*7c478bd9Sstevel@tonic-gate 			break;
1522*7c478bd9Sstevel@tonic-gate 		case TOK_ENDNODE:
1523*7c478bd9Sstevel@tonic-gate 			*last_processed_index = index;
1524*7c478bd9Sstevel@tonic-gate 			return (PICL_SUCCESS);
1525*7c478bd9Sstevel@tonic-gate 		case TOK_PROP:
1526*7c478bd9Sstevel@tonic-gate 			err =  process_prop(cmds, &commands[index], parent);
1527*7c478bd9Sstevel@tonic-gate 			break;
1528*7c478bd9Sstevel@tonic-gate 		case TOK_REFPROP:
1529*7c478bd9Sstevel@tonic-gate 			err = process_refprop(cmds, &commands[index], parent);
1530*7c478bd9Sstevel@tonic-gate 			/* no reference node */
1531*7c478bd9Sstevel@tonic-gate 			if (err == PICL_NOTNODE) {
1532*7c478bd9Sstevel@tonic-gate 				err = PICL_SUCCESS;	/* discard prop */
1533*7c478bd9Sstevel@tonic-gate 				/* discard row by setting nproph = 0 */
1534*7c478bd9Sstevel@tonic-gate 				if (cmds->inside_row_block)
1535*7c478bd9Sstevel@tonic-gate 					cmds->commands[cmds->current_row]
1536*7c478bd9Sstevel@tonic-gate 					    .rowcmd_nproph = 0;
1537*7c478bd9Sstevel@tonic-gate 			}
1538*7c478bd9Sstevel@tonic-gate 			break;
1539*7c478bd9Sstevel@tonic-gate 		case TOK_REFNODE:
1540*7c478bd9Sstevel@tonic-gate 			err =  process_refnode(&commands[index], parent);
1541*7c478bd9Sstevel@tonic-gate 			break;
1542*7c478bd9Sstevel@tonic-gate 		case TOK_TABLE:
1543*7c478bd9Sstevel@tonic-gate 			cmds->inside_table_block = 1;
1544*7c478bd9Sstevel@tonic-gate 			err = process_table(&commands[index], parent);
1545*7c478bd9Sstevel@tonic-gate 			cmds->current_tbl = index;
1546*7c478bd9Sstevel@tonic-gate 			break;
1547*7c478bd9Sstevel@tonic-gate 		case TOK_ENDTABLE:
1548*7c478bd9Sstevel@tonic-gate 			cmds->inside_table_block = 0;
1549*7c478bd9Sstevel@tonic-gate 			cmds->current_tbl = 0;
1550*7c478bd9Sstevel@tonic-gate 			break;
1551*7c478bd9Sstevel@tonic-gate 		case TOK_ROW:
1552*7c478bd9Sstevel@tonic-gate 			cmds->inside_row_block = 1;
1553*7c478bd9Sstevel@tonic-gate 			err = process_row(&commands[index]);
1554*7c478bd9Sstevel@tonic-gate 			cmds->current_row = index;
1555*7c478bd9Sstevel@tonic-gate 			break;
1556*7c478bd9Sstevel@tonic-gate 		case TOK_ENDROW:
1557*7c478bd9Sstevel@tonic-gate 			err = process_endrow(cmds);
1558*7c478bd9Sstevel@tonic-gate 			cmds->inside_row_block = 0;
1559*7c478bd9Sstevel@tonic-gate 			cmds->current_row = 0;
1560*7c478bd9Sstevel@tonic-gate 			break;
1561*7c478bd9Sstevel@tonic-gate 		case TOK_VERBOSE:
1562*7c478bd9Sstevel@tonic-gate 			err = process_verbose(cmds, &commands[index]);
1563*7c478bd9Sstevel@tonic-gate 			break;
1564*7c478bd9Sstevel@tonic-gate 		default:	/* won't reach here */
1565*7c478bd9Sstevel@tonic-gate 			err =  PICL_FAILURE;
1566*7c478bd9Sstevel@tonic-gate 			break;
1567*7c478bd9Sstevel@tonic-gate 		}
1568*7c478bd9Sstevel@tonic-gate 
1569*7c478bd9Sstevel@tonic-gate 		if ((err != PICL_SUCCESS) && (err != PICL_PROPEXISTS)) {
1570*7c478bd9Sstevel@tonic-gate 			*last_processed_index = index;
1571*7c478bd9Sstevel@tonic-gate 			return (err);
1572*7c478bd9Sstevel@tonic-gate 		}
1573*7c478bd9Sstevel@tonic-gate 	}
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate 	/* reach last command */
1576*7c478bd9Sstevel@tonic-gate 	*last_processed_index = cmds->count - 1;
1577*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
1578*7c478bd9Sstevel@tonic-gate }
1579*7c478bd9Sstevel@tonic-gate 
1580*7c478bd9Sstevel@tonic-gate /*
1581*7c478bd9Sstevel@tonic-gate  * clean up the commands buffer
1582*7c478bd9Sstevel@tonic-gate  */
1583*7c478bd9Sstevel@tonic-gate static void
1584*7c478bd9Sstevel@tonic-gate clean_up(cmdbuf_t *cmds)
1585*7c478bd9Sstevel@tonic-gate {
1586*7c478bd9Sstevel@tonic-gate 	int	cmd_index;
1587*7c478bd9Sstevel@tonic-gate 
1588*7c478bd9Sstevel@tonic-gate 	for (cmd_index = 0; cmd_index < cmds->count; cmd_index++) {
1589*7c478bd9Sstevel@tonic-gate 		switch (cmds->commands[cmd_index].type) {
1590*7c478bd9Sstevel@tonic-gate 		case TOK_CLASSPATH:
1591*7c478bd9Sstevel@tonic-gate 		case TOK_NAMEPATH:
1592*7c478bd9Sstevel@tonic-gate 			free_path(&cmds->commands[cmd_index]);
1593*7c478bd9Sstevel@tonic-gate 			break;
1594*7c478bd9Sstevel@tonic-gate 		case TOK_NODE:
1595*7c478bd9Sstevel@tonic-gate 			free_node(&cmds->commands[cmd_index]);
1596*7c478bd9Sstevel@tonic-gate 			break;
1597*7c478bd9Sstevel@tonic-gate 		case TOK_PROP:
1598*7c478bd9Sstevel@tonic-gate 			free_prop(&cmds->commands[cmd_index]);
1599*7c478bd9Sstevel@tonic-gate 			break;
1600*7c478bd9Sstevel@tonic-gate 		case TOK_REFPROP:
1601*7c478bd9Sstevel@tonic-gate 			free_refprop(&cmds->commands[cmd_index]);
1602*7c478bd9Sstevel@tonic-gate 			break;
1603*7c478bd9Sstevel@tonic-gate 		case TOK_REFNODE:
1604*7c478bd9Sstevel@tonic-gate 			free_refnode(&cmds->commands[cmd_index]);
1605*7c478bd9Sstevel@tonic-gate 			break;
1606*7c478bd9Sstevel@tonic-gate 		case TOK_TABLE:
1607*7c478bd9Sstevel@tonic-gate 			free_table(&cmds->commands[cmd_index]);
1608*7c478bd9Sstevel@tonic-gate 			break;
1609*7c478bd9Sstevel@tonic-gate 		case TOK_ENDTABLE:
1610*7c478bd9Sstevel@tonic-gate 		case TOK_ROW:
1611*7c478bd9Sstevel@tonic-gate 		case TOK_ENDROW:
1612*7c478bd9Sstevel@tonic-gate 		case TOK_ENDNODE:
1613*7c478bd9Sstevel@tonic-gate 		case TOK_VERBOSE:
1614*7c478bd9Sstevel@tonic-gate 		default:
1615*7c478bd9Sstevel@tonic-gate 			break;
1616*7c478bd9Sstevel@tonic-gate 		}
1617*7c478bd9Sstevel@tonic-gate 	}
1618*7c478bd9Sstevel@tonic-gate 	if (cmds->commands)
1619*7c478bd9Sstevel@tonic-gate 		free(cmds->commands);
1620*7c478bd9Sstevel@tonic-gate }
1621*7c478bd9Sstevel@tonic-gate 
1622*7c478bd9Sstevel@tonic-gate /*
1623*7c478bd9Sstevel@tonic-gate  * Parse the configuration file and create nodes/properties under nh
1624*7c478bd9Sstevel@tonic-gate  *
1625*7c478bd9Sstevel@tonic-gate  * It checks the syntax first.  If there is any syntax error,
1626*7c478bd9Sstevel@tonic-gate  * it returns 1 and won't continue processing the file to add nodes or props.
1627*7c478bd9Sstevel@tonic-gate  *
1628*7c478bd9Sstevel@tonic-gate  * If any error happens during command processing, all nodes
1629*7c478bd9Sstevel@tonic-gate  * and properties just created will be deleted, i.e. undo
1630*7c478bd9Sstevel@tonic-gate  * commands which have been processed.  It returns 1.
1631*7c478bd9Sstevel@tonic-gate  *
1632*7c478bd9Sstevel@tonic-gate  * If success, return 0.
1633*7c478bd9Sstevel@tonic-gate  */
1634*7c478bd9Sstevel@tonic-gate int
1635*7c478bd9Sstevel@tonic-gate picld_pluginutil_parse_config_file(picl_nodehdl_t nh, const char *filename)
1636*7c478bd9Sstevel@tonic-gate {
1637*7c478bd9Sstevel@tonic-gate 	FILE		*ifp;
1638*7c478bd9Sstevel@tonic-gate 	int		last_processed_index;
1639*7c478bd9Sstevel@tonic-gate 	int		err;
1640*7c478bd9Sstevel@tonic-gate 	cmdbuf_t	*cmds;
1641*7c478bd9Sstevel@tonic-gate 
1642*7c478bd9Sstevel@tonic-gate 	/* set correct locale for use inside pluginutil */
1643*7c478bd9Sstevel@tonic-gate 	setlocale(LC_ALL, "C");
1644*7c478bd9Sstevel@tonic-gate 
1645*7c478bd9Sstevel@tonic-gate 	/*
1646*7c478bd9Sstevel@tonic-gate 	 * Initialize the command buffer
1647*7c478bd9Sstevel@tonic-gate 	 */
1648*7c478bd9Sstevel@tonic-gate 
1649*7c478bd9Sstevel@tonic-gate 	cmds = malloc(sizeof (*cmds));
1650*7c478bd9Sstevel@tonic-gate 	if (cmds == NULL) {
1651*7c478bd9Sstevel@tonic-gate 		setlocale(LC_ALL, "");
1652*7c478bd9Sstevel@tonic-gate 		return (1);
1653*7c478bd9Sstevel@tonic-gate 	}
1654*7c478bd9Sstevel@tonic-gate 
1655*7c478bd9Sstevel@tonic-gate 	memset(cmds, 0, sizeof (cmdbuf_t));
1656*7c478bd9Sstevel@tonic-gate 
1657*7c478bd9Sstevel@tonic-gate 	cmds->fname = filename;
1658*7c478bd9Sstevel@tonic-gate 
1659*7c478bd9Sstevel@tonic-gate 	ifp = fopen(filename, "r");
1660*7c478bd9Sstevel@tonic-gate 	if (ifp == NULL) {
1661*7c478bd9Sstevel@tonic-gate 		setlocale(LC_ALL, "");
1662*7c478bd9Sstevel@tonic-gate 		return (1);
1663*7c478bd9Sstevel@tonic-gate 	}
1664*7c478bd9Sstevel@tonic-gate 
1665*7c478bd9Sstevel@tonic-gate 	/*
1666*7c478bd9Sstevel@tonic-gate 	 * check the syntax of the configuration file
1667*7c478bd9Sstevel@tonic-gate 	 */
1668*7c478bd9Sstevel@tonic-gate 	err = check_conffile_syntax(cmds, ifp);
1669*7c478bd9Sstevel@tonic-gate 
1670*7c478bd9Sstevel@tonic-gate 	(void) fclose(ifp);
1671*7c478bd9Sstevel@tonic-gate 
1672*7c478bd9Sstevel@tonic-gate 	if (err != EC_SYNTAX_OK) {
1673*7c478bd9Sstevel@tonic-gate 		clean_up(cmds);
1674*7c478bd9Sstevel@tonic-gate 		free(cmds);
1675*7c478bd9Sstevel@tonic-gate 		setlocale(LC_ALL, "");
1676*7c478bd9Sstevel@tonic-gate 		return (1);
1677*7c478bd9Sstevel@tonic-gate 	}
1678*7c478bd9Sstevel@tonic-gate 
1679*7c478bd9Sstevel@tonic-gate 	/*
1680*7c478bd9Sstevel@tonic-gate 	 * Process the commands
1681*7c478bd9Sstevel@tonic-gate 	 */
1682*7c478bd9Sstevel@tonic-gate 	err = process_commands(cmds, STARTING_INDEX, nh, &last_processed_index);
1683*7c478bd9Sstevel@tonic-gate 
1684*7c478bd9Sstevel@tonic-gate 	/*
1685*7c478bd9Sstevel@tonic-gate 	 * If any PICL error, remove the newly created node/prop
1686*7c478bd9Sstevel@tonic-gate 	 * handles from the PICL tree.
1687*7c478bd9Sstevel@tonic-gate 	 */
1688*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
1689*7c478bd9Sstevel@tonic-gate 		undo_commands(cmds, last_processed_index);
1690*7c478bd9Sstevel@tonic-gate 		if (cmds->verbose)
1691*7c478bd9Sstevel@tonic-gate 			verbose_log(LOG_ERR, err_msg[EC_PICL_ERR], filename,
1692*7c478bd9Sstevel@tonic-gate 			    err);
1693*7c478bd9Sstevel@tonic-gate 	}
1694*7c478bd9Sstevel@tonic-gate 
1695*7c478bd9Sstevel@tonic-gate 	clean_up(cmds);
1696*7c478bd9Sstevel@tonic-gate 	free(cmds);
1697*7c478bd9Sstevel@tonic-gate 
1698*7c478bd9Sstevel@tonic-gate 	/* reset the locale */
1699*7c478bd9Sstevel@tonic-gate 	setlocale(LC_ALL, "");
1700*7c478bd9Sstevel@tonic-gate 
1701*7c478bd9Sstevel@tonic-gate 	return ((err == PICL_SUCCESS) ? 0 : 1);
1702*7c478bd9Sstevel@tonic-gate }
1703