xref: /titanic_54/usr/src/cmd/picl/prtpicl/prtpicl.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 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 #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate #include <alloca.h>
34*7c478bd9Sstevel@tonic-gate #include <libintl.h>
35*7c478bd9Sstevel@tonic-gate #include <locale.h>
36*7c478bd9Sstevel@tonic-gate #include <unistd.h>
37*7c478bd9Sstevel@tonic-gate #include <assert.h>
38*7c478bd9Sstevel@tonic-gate #include <inttypes.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/termios.h>
40*7c478bd9Sstevel@tonic-gate #include <picl.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate /*
43*7c478bd9Sstevel@tonic-gate  * Constant definitions and macros
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate #define	COL_DELIM		"|"
46*7c478bd9Sstevel@tonic-gate #define	ROOT_LEVEL		0
47*7c478bd9Sstevel@tonic-gate #define	LEVEL_INDENT		4
48*7c478bd9Sstevel@tonic-gate #define	PROP_INDENT		2
49*7c478bd9Sstevel@tonic-gate #define	NCOLS			80
50*7c478bd9Sstevel@tonic-gate #define	NODEINFO_LEFT_MARGIN(x)	(x * LEVEL_INDENT)
51*7c478bd9Sstevel@tonic-gate #define	PROPINFO_LEFT_MARGIN(x)	(x * LEVEL_INDENT + PROP_INDENT)
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate #define	PRIxPICLTBL		PRIx64
54*7c478bd9Sstevel@tonic-gate #define	PRIxPICLHDL		PRIx64
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate /*
57*7c478bd9Sstevel@tonic-gate  * Program variables
58*7c478bd9Sstevel@tonic-gate  */
59*7c478bd9Sstevel@tonic-gate static	char	*prog;
60*7c478bd9Sstevel@tonic-gate static	int	verbose_mode = 0;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate /*
63*7c478bd9Sstevel@tonic-gate  * Error codes
64*7c478bd9Sstevel@tonic-gate  */
65*7c478bd9Sstevel@tonic-gate #define	EM_USAGE		0
66*7c478bd9Sstevel@tonic-gate #define	EM_INIT			1
67*7c478bd9Sstevel@tonic-gate #define	EM_GETROOT		2
68*7c478bd9Sstevel@tonic-gate #define	EM_GETPVAL		3
69*7c478bd9Sstevel@tonic-gate #define	EM_GETNXTBYCOL		4
70*7c478bd9Sstevel@tonic-gate #define	EM_GETNXTBYROW		5
71*7c478bd9Sstevel@tonic-gate #define	EM_GETPINFO		6
72*7c478bd9Sstevel@tonic-gate #define	EM_GETPVALBYNAME	7
73*7c478bd9Sstevel@tonic-gate #define	EM_GETPROPBYNAME	8
74*7c478bd9Sstevel@tonic-gate #define	EM_INT_INVSIZE		9
75*7c478bd9Sstevel@tonic-gate #define	EM_UINT_INVSIZE		10
76*7c478bd9Sstevel@tonic-gate #define	EM_FLOAT_INVSIZE	11
77*7c478bd9Sstevel@tonic-gate #define	EM_TS_INVALID		12
78*7c478bd9Sstevel@tonic-gate #define	EM_TABLE_INVSIZE	13
79*7c478bd9Sstevel@tonic-gate #define	EM_REF_INVSIZE		14
80*7c478bd9Sstevel@tonic-gate #define	EM_TYPE_UNKNOWN		15
81*7c478bd9Sstevel@tonic-gate #define	EM_TS_OVERFLOW		16
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /*
84*7c478bd9Sstevel@tonic-gate  * Error mesage texts
85*7c478bd9Sstevel@tonic-gate  */
86*7c478bd9Sstevel@tonic-gate static	char	*err_msg[] = {
87*7c478bd9Sstevel@tonic-gate 	/* program usage */
88*7c478bd9Sstevel@tonic-gate 	"Usage: %s [-v] [-c <picl_class>]\n",			/*  0 */
89*7c478bd9Sstevel@tonic-gate 	/* picl call failed messages */
90*7c478bd9Sstevel@tonic-gate 	"picl_initialize failed: %s\n",				/*  1 */
91*7c478bd9Sstevel@tonic-gate 	"picl_get_root failed: %s\n",				/*  2 */
92*7c478bd9Sstevel@tonic-gate 	"picl_get_propval failed: %s\n",			/*  3 */
93*7c478bd9Sstevel@tonic-gate 	"picl_get_next_by_col failed: %s\n",			/*  4 */
94*7c478bd9Sstevel@tonic-gate 	"picl_get_next_by_row failed: %s\n",			/*  5 */
95*7c478bd9Sstevel@tonic-gate 	"picl_get_propinfo failed: %s\n",			/*  6 */
96*7c478bd9Sstevel@tonic-gate 	"picl_get_propval_by_name failed: %s\n",		/*  7 */
97*7c478bd9Sstevel@tonic-gate 	"picl_get_prop_by_name failed: %s\n",			/*  8 */
98*7c478bd9Sstevel@tonic-gate 	/* invalid data error messages */
99*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid int size %d\n",		/*  9 */
100*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid unsigned int size %d\n",	/* 10 */
101*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid float size %d\n",		/* 11 */
102*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid timestamp\n",		/* 12 */
103*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid table handle size %d\n",	/* 13 */
104*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid reference size %d\n",	/* 14 */
105*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: unknown type\n",			/* 15 */
106*7c478bd9Sstevel@tonic-gate 	"picl_get_propval: timestamp value too large\n"		/* 16 */
107*7c478bd9Sstevel@tonic-gate };
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
110*7c478bd9Sstevel@tonic-gate static void
111*7c478bd9Sstevel@tonic-gate print_errmsg(char *message, ...)
112*7c478bd9Sstevel@tonic-gate {
113*7c478bd9Sstevel@tonic-gate 	va_list ap;
114*7c478bd9Sstevel@tonic-gate 
115*7c478bd9Sstevel@tonic-gate 	va_start(ap, message);
116*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", prog);
117*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, message, ap);
118*7c478bd9Sstevel@tonic-gate 	va_end(ap);
119*7c478bd9Sstevel@tonic-gate }
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate /*
122*7c478bd9Sstevel@tonic-gate  * Print prtpicl usage
123*7c478bd9Sstevel@tonic-gate  */
124*7c478bd9Sstevel@tonic-gate static void
125*7c478bd9Sstevel@tonic-gate usage(void)
126*7c478bd9Sstevel@tonic-gate {
127*7c478bd9Sstevel@tonic-gate 	print_errmsg(gettext(err_msg[EM_USAGE]), prog);
128*7c478bd9Sstevel@tonic-gate 	exit(1);
129*7c478bd9Sstevel@tonic-gate }
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate /*
132*7c478bd9Sstevel@tonic-gate  * print a bytearray value and format it to fit in 80 columns
133*7c478bd9Sstevel@tonic-gate  */
134*7c478bd9Sstevel@tonic-gate static void
135*7c478bd9Sstevel@tonic-gate print_bytearray(int lvl, uint8_t *vbuf, size_t nbytes)
136*7c478bd9Sstevel@tonic-gate {
137*7c478bd9Sstevel@tonic-gate 	int		cnum;
138*7c478bd9Sstevel@tonic-gate 	int		columns;
139*7c478bd9Sstevel@tonic-gate 	char		*s;
140*7c478bd9Sstevel@tonic-gate 	struct winsize	winsize;
141*7c478bd9Sstevel@tonic-gate 	size_t		i;
142*7c478bd9Sstevel@tonic-gate 
143*7c478bd9Sstevel@tonic-gate 	/*
144*7c478bd9Sstevel@tonic-gate 	 * The COLUMNS_PER_BYTE is set to 4 to match the printf
145*7c478bd9Sstevel@tonic-gate 	 * format used below, i.e. " %02x ", to print a byte
146*7c478bd9Sstevel@tonic-gate 	 */
147*7c478bd9Sstevel@tonic-gate #define	COLUMNS_PER_BYTE	4
148*7c478bd9Sstevel@tonic-gate 
149*7c478bd9Sstevel@tonic-gate 	/*
150*7c478bd9Sstevel@tonic-gate 	 * Kind of a hack to determine the width of the output...
151*7c478bd9Sstevel@tonic-gate 	 */
152*7c478bd9Sstevel@tonic-gate 	columns = NCOLS;
153*7c478bd9Sstevel@tonic-gate 	if ((s = getenv("COLUMNS")) != NULL && (cnum = atoi(s)) > 0)
154*7c478bd9Sstevel@tonic-gate 		columns = cnum;
155*7c478bd9Sstevel@tonic-gate 	else if (isatty(fileno(stdout)) &&
156*7c478bd9Sstevel@tonic-gate 	    ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 &&
157*7c478bd9Sstevel@tonic-gate 	    winsize.ws_col != 0)
158*7c478bd9Sstevel@tonic-gate 		columns = winsize.ws_col;
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	cnum = PROPINFO_LEFT_MARGIN(lvl);
162*7c478bd9Sstevel@tonic-gate 	if ((nbytes * COLUMNS_PER_BYTE + cnum) > columns) {
163*7c478bd9Sstevel@tonic-gate 		(void) printf("\n");
164*7c478bd9Sstevel@tonic-gate 		cnum = 0;
165*7c478bd9Sstevel@tonic-gate 	}
166*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nbytes; ++i) {
167*7c478bd9Sstevel@tonic-gate 		if (cnum > columns - COLUMNS_PER_BYTE) {
168*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
169*7c478bd9Sstevel@tonic-gate 			cnum = 0;
170*7c478bd9Sstevel@tonic-gate 		}
171*7c478bd9Sstevel@tonic-gate 		(void) printf(" %02x ", vbuf[i]);
172*7c478bd9Sstevel@tonic-gate 		cnum += COLUMNS_PER_BYTE;
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate /*
177*7c478bd9Sstevel@tonic-gate  * Print a property's value
178*7c478bd9Sstevel@tonic-gate  * If the property is read protected, return success.
179*7c478bd9Sstevel@tonic-gate  * If an invalid/stale handle error is encountered, return the error. For
180*7c478bd9Sstevel@tonic-gate  * other errors, print a message and return success.
181*7c478bd9Sstevel@tonic-gate  */
182*7c478bd9Sstevel@tonic-gate static int
183*7c478bd9Sstevel@tonic-gate print_propval(int lvl, picl_prophdl_t proph, const picl_propinfo_t *propinfo)
184*7c478bd9Sstevel@tonic-gate {
185*7c478bd9Sstevel@tonic-gate 	int		err;
186*7c478bd9Sstevel@tonic-gate 	void		*vbuf;
187*7c478bd9Sstevel@tonic-gate 	char		*str;
188*7c478bd9Sstevel@tonic-gate 	uint64_t	val64;
189*7c478bd9Sstevel@tonic-gate 	time_t		tmp;
190*7c478bd9Sstevel@tonic-gate 
191*7c478bd9Sstevel@tonic-gate 	/*
192*7c478bd9Sstevel@tonic-gate 	 * If property is read protected, print a message and continue
193*7c478bd9Sstevel@tonic-gate 	 */
194*7c478bd9Sstevel@tonic-gate 	if (!(propinfo->accessmode & PICL_READ)) {
195*7c478bd9Sstevel@tonic-gate 		(void) printf("<%s>", gettext("WRITE-ONLY"));
196*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
197*7c478bd9Sstevel@tonic-gate 	}
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	vbuf = alloca(propinfo->size);
200*7c478bd9Sstevel@tonic-gate 	if (propinfo->type == PICL_PTYPE_VOID)
201*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 	err = picl_get_propval(proph, vbuf, propinfo->size);
204*7c478bd9Sstevel@tonic-gate 	/*
205*7c478bd9Sstevel@tonic-gate 	 * If the error is not a stale/invalid handle or noresponse, continue
206*7c478bd9Sstevel@tonic-gate 	 * by ignoring the error/skipping the property.
207*7c478bd9Sstevel@tonic-gate 	 */
208*7c478bd9Sstevel@tonic-gate 	if ((err == PICL_INVALIDHANDLE) || (err == PICL_STALEHANDLE) ||
209*7c478bd9Sstevel@tonic-gate 	    (err == PICL_NORESPONSE))
210*7c478bd9Sstevel@tonic-gate 		return (err);
211*7c478bd9Sstevel@tonic-gate 	else if (err != PICL_SUCCESS) {
212*7c478bd9Sstevel@tonic-gate 		(void) printf("<%s: %s>", gettext("ERROR"), picl_strerror(err));
213*7c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
214*7c478bd9Sstevel@tonic-gate 	}
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	assert(vbuf != NULL);
217*7c478bd9Sstevel@tonic-gate 	assert(propinfo->size > 0);
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	switch (propinfo->type) {
220*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_CHARSTRING:
221*7c478bd9Sstevel@tonic-gate 		(void) printf(" %s ", (char *)vbuf);
222*7c478bd9Sstevel@tonic-gate 		break;
223*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_INT:
224*7c478bd9Sstevel@tonic-gate 		switch (propinfo->size) {
225*7c478bd9Sstevel@tonic-gate 		case sizeof (int8_t):
226*7c478bd9Sstevel@tonic-gate 			/* avoid using PRId8 until lint recognizes hh */
227*7c478bd9Sstevel@tonic-gate 			(void) printf(" %d ", *(int8_t *)vbuf);
228*7c478bd9Sstevel@tonic-gate 			break;
229*7c478bd9Sstevel@tonic-gate 		case sizeof (int16_t):
230*7c478bd9Sstevel@tonic-gate 			(void) printf(" %" PRId16 " ", *(int16_t *)vbuf);
231*7c478bd9Sstevel@tonic-gate 			break;
232*7c478bd9Sstevel@tonic-gate 		case sizeof (int32_t):
233*7c478bd9Sstevel@tonic-gate 			(void) printf(" %" PRId32 " ", *(int32_t *)vbuf);
234*7c478bd9Sstevel@tonic-gate 			break;
235*7c478bd9Sstevel@tonic-gate 		case sizeof (int64_t):
236*7c478bd9Sstevel@tonic-gate 			(void) printf(" %" PRId64 " ", *(int64_t *)vbuf);
237*7c478bd9Sstevel@tonic-gate 			break;
238*7c478bd9Sstevel@tonic-gate 		default:
239*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_INT_INVSIZE]),
240*7c478bd9Sstevel@tonic-gate 			    propinfo->size);
241*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
242*7c478bd9Sstevel@tonic-gate 		}
243*7c478bd9Sstevel@tonic-gate 		break;
244*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_UNSIGNED_INT:
245*7c478bd9Sstevel@tonic-gate 		switch (propinfo->size) {
246*7c478bd9Sstevel@tonic-gate 		case sizeof (uint8_t):
247*7c478bd9Sstevel@tonic-gate 			/* avoid using PRIx8 until lint recognizes hh */
248*7c478bd9Sstevel@tonic-gate 			(void) printf(" %#x ", *(uint8_t *)vbuf);
249*7c478bd9Sstevel@tonic-gate 			break;
250*7c478bd9Sstevel@tonic-gate 		case sizeof (uint16_t):
251*7c478bd9Sstevel@tonic-gate 			(void) printf(" %#" PRIx16 " ", *(uint16_t *)vbuf);
252*7c478bd9Sstevel@tonic-gate 			break;
253*7c478bd9Sstevel@tonic-gate 		case sizeof (uint32_t):
254*7c478bd9Sstevel@tonic-gate 			(void) printf(" %#" PRIx32 " ", *(uint32_t *)vbuf);
255*7c478bd9Sstevel@tonic-gate 			break;
256*7c478bd9Sstevel@tonic-gate 		case sizeof (uint64_t):
257*7c478bd9Sstevel@tonic-gate 			(void) printf(" %#" PRIx64 " ", *(uint64_t *)vbuf);
258*7c478bd9Sstevel@tonic-gate 			break;
259*7c478bd9Sstevel@tonic-gate 		default:
260*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_UINT_INVSIZE]),
261*7c478bd9Sstevel@tonic-gate 			    propinfo->size);
262*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
263*7c478bd9Sstevel@tonic-gate 		}
264*7c478bd9Sstevel@tonic-gate 		break;
265*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_FLOAT:
266*7c478bd9Sstevel@tonic-gate 		switch (propinfo->size) {
267*7c478bd9Sstevel@tonic-gate 		case sizeof (float):
268*7c478bd9Sstevel@tonic-gate 			(void) printf(" %f ", *(float *)vbuf);
269*7c478bd9Sstevel@tonic-gate 			break;
270*7c478bd9Sstevel@tonic-gate 		case sizeof (double):
271*7c478bd9Sstevel@tonic-gate 			(void) printf(" %f ", *(double *)vbuf);
272*7c478bd9Sstevel@tonic-gate 			break;
273*7c478bd9Sstevel@tonic-gate 		default:
274*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_FLOAT_INVSIZE]),
275*7c478bd9Sstevel@tonic-gate 			    propinfo->size);
276*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
277*7c478bd9Sstevel@tonic-gate 		}
278*7c478bd9Sstevel@tonic-gate 		break;
279*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_TIMESTAMP:
280*7c478bd9Sstevel@tonic-gate 		val64 = *(uint64_t *)vbuf;
281*7c478bd9Sstevel@tonic-gate 		tmp = (time_t)val64;
282*7c478bd9Sstevel@tonic-gate 		if ((uint64_t)tmp != val64) {
283*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_TS_OVERFLOW]));
284*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
285*7c478bd9Sstevel@tonic-gate 		}
286*7c478bd9Sstevel@tonic-gate 		str = ctime(&tmp);
287*7c478bd9Sstevel@tonic-gate 		if (str == NULL) {
288*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_TS_INVALID]));
289*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
290*7c478bd9Sstevel@tonic-gate 		}
291*7c478bd9Sstevel@tonic-gate 		str[strlen(str) - 1] = '\0';
292*7c478bd9Sstevel@tonic-gate 		(void) printf(" %s ", str);
293*7c478bd9Sstevel@tonic-gate 		break;
294*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_TABLE:
295*7c478bd9Sstevel@tonic-gate 		if (propinfo->size != sizeof (picl_prophdl_t)) {
296*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_TABLE_INVSIZE]),
297*7c478bd9Sstevel@tonic-gate 			    propinfo->size);
298*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
299*7c478bd9Sstevel@tonic-gate 		}
300*7c478bd9Sstevel@tonic-gate 		(void) printf("(%" PRIxPICLTBL "TBL) ",
301*7c478bd9Sstevel@tonic-gate 		    *(picl_prophdl_t *)vbuf);
302*7c478bd9Sstevel@tonic-gate 		break;
303*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_REFERENCE:
304*7c478bd9Sstevel@tonic-gate 		if (propinfo->size != sizeof (picl_nodehdl_t)) {
305*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_REF_INVSIZE]),
306*7c478bd9Sstevel@tonic-gate 			    propinfo->size);
307*7c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
308*7c478bd9Sstevel@tonic-gate 		}
309*7c478bd9Sstevel@tonic-gate 		(void) printf(" (%" PRIxPICLHDL "H) ", *(picl_nodehdl_t *)vbuf);
310*7c478bd9Sstevel@tonic-gate 		break;
311*7c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_BYTEARRAY:
312*7c478bd9Sstevel@tonic-gate 		print_bytearray(lvl, vbuf, propinfo->size);
313*7c478bd9Sstevel@tonic-gate 		break;
314*7c478bd9Sstevel@tonic-gate 	default:
315*7c478bd9Sstevel@tonic-gate 		print_errmsg(gettext(err_msg[EM_TYPE_UNKNOWN]));
316*7c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
317*7c478bd9Sstevel@tonic-gate 	}
318*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate /*
322*7c478bd9Sstevel@tonic-gate  * print table property value
323*7c478bd9Sstevel@tonic-gate  */
324*7c478bd9Sstevel@tonic-gate static int
325*7c478bd9Sstevel@tonic-gate print_table_prop(int lvl, picl_prophdl_t tblh)
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	rowproph;
328*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	colproph;
329*7c478bd9Sstevel@tonic-gate 	int		err;
330*7c478bd9Sstevel@tonic-gate 	picl_propinfo_t	propinfo;
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 	for (err = picl_get_next_by_col(tblh, &rowproph); err != PICL_ENDOFLIST;
333*7c478bd9Sstevel@tonic-gate 	    err = picl_get_next_by_col(rowproph, &rowproph)) {
334*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
335*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETNXTBYCOL]),
336*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
337*7c478bd9Sstevel@tonic-gate 			return (err);
338*7c478bd9Sstevel@tonic-gate 		}
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate 		(void) printf("%*s %s", PROPINFO_LEFT_MARGIN(lvl), " ",
341*7c478bd9Sstevel@tonic-gate 		    COL_DELIM);
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 		for (colproph = rowproph; err != PICL_ENDOFLIST;
344*7c478bd9Sstevel@tonic-gate 		    err = picl_get_next_by_row(colproph, &colproph)) {
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
347*7c478bd9Sstevel@tonic-gate 				print_errmsg(gettext(err_msg[EM_GETNXTBYROW]),
348*7c478bd9Sstevel@tonic-gate 				    picl_strerror(err));
349*7c478bd9Sstevel@tonic-gate 				return (err);
350*7c478bd9Sstevel@tonic-gate 			}
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 			err = picl_get_propinfo(colproph, &propinfo);
353*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
354*7c478bd9Sstevel@tonic-gate 				print_errmsg(gettext(err_msg[EM_GETPINFO]),
355*7c478bd9Sstevel@tonic-gate 				    picl_strerror(err));
356*7c478bd9Sstevel@tonic-gate 				return (err);
357*7c478bd9Sstevel@tonic-gate 			}
358*7c478bd9Sstevel@tonic-gate 
359*7c478bd9Sstevel@tonic-gate 			err = print_propval(lvl, colproph, &propinfo);
360*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
361*7c478bd9Sstevel@tonic-gate 				return (err);
362*7c478bd9Sstevel@tonic-gate 			(void) printf(COL_DELIM);
363*7c478bd9Sstevel@tonic-gate 		}
364*7c478bd9Sstevel@tonic-gate 		(void) printf("\n");
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate /*
370*7c478bd9Sstevel@tonic-gate  * Print the properties (name = value) of a node. If an error occurs
371*7c478bd9Sstevel@tonic-gate  * when printing the property value, stop. print_propval() suppresses
372*7c478bd9Sstevel@tonic-gate  * errors during getting property value except for stale/invalid handle
373*7c478bd9Sstevel@tonic-gate  * and no response errors.
374*7c478bd9Sstevel@tonic-gate  */
375*7c478bd9Sstevel@tonic-gate static int
376*7c478bd9Sstevel@tonic-gate print_proplist(int lvl, picl_nodehdl_t nodeh)
377*7c478bd9Sstevel@tonic-gate {
378*7c478bd9Sstevel@tonic-gate 	int		err;
379*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	proph;
380*7c478bd9Sstevel@tonic-gate 	picl_propinfo_t	propinfo;
381*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	tblh;
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	for (err = picl_get_first_prop(nodeh, &proph); err == PICL_SUCCESS;
384*7c478bd9Sstevel@tonic-gate 	    err = picl_get_next_prop(proph, &proph)) {
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 		err = picl_get_propinfo(proph, &propinfo);
387*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
388*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPINFO]),
389*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
390*7c478bd9Sstevel@tonic-gate 			return (err);
391*7c478bd9Sstevel@tonic-gate 		}
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 		if (propinfo.type == PICL_PTYPE_VOID)
394*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s:%s\n", PROPINFO_LEFT_MARGIN(lvl),
395*7c478bd9Sstevel@tonic-gate 			    " ", propinfo.name);
396*7c478bd9Sstevel@tonic-gate 		else {
397*7c478bd9Sstevel@tonic-gate 			(void) printf("%*s:%s\t", PROPINFO_LEFT_MARGIN(lvl),
398*7c478bd9Sstevel@tonic-gate 			    " ", propinfo.name);
399*7c478bd9Sstevel@tonic-gate 			err = print_propval(lvl, proph, &propinfo);
400*7c478bd9Sstevel@tonic-gate 			(void) printf("\n");
401*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
402*7c478bd9Sstevel@tonic-gate 				return (err);
403*7c478bd9Sstevel@tonic-gate 		}
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 		/*
406*7c478bd9Sstevel@tonic-gate 		 * Expand the table property
407*7c478bd9Sstevel@tonic-gate 		 */
408*7c478bd9Sstevel@tonic-gate 		if (propinfo.type == PICL_PTYPE_TABLE) {
409*7c478bd9Sstevel@tonic-gate 			err = picl_get_propval(proph, &tblh, propinfo.size);
410*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
411*7c478bd9Sstevel@tonic-gate 				print_errmsg(gettext(err_msg[EM_GETPVAL]),
412*7c478bd9Sstevel@tonic-gate 				    picl_strerror(err));
413*7c478bd9Sstevel@tonic-gate 				return (err);
414*7c478bd9Sstevel@tonic-gate 			}
415*7c478bd9Sstevel@tonic-gate 			err = print_table_prop(lvl, tblh);
416*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
417*7c478bd9Sstevel@tonic-gate 				return (err);
418*7c478bd9Sstevel@tonic-gate 		}
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
421*7c478bd9Sstevel@tonic-gate }
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate /*
424*7c478bd9Sstevel@tonic-gate  * Recursively print the PICL tree
425*7c478bd9Sstevel@tonic-gate  * When piclclass is specified, print only the nodes of that class.
426*7c478bd9Sstevel@tonic-gate  */
427*7c478bd9Sstevel@tonic-gate static int
428*7c478bd9Sstevel@tonic-gate print_tree_by_class(int lvl, picl_nodehdl_t nodeh, char *piclclass)
429*7c478bd9Sstevel@tonic-gate {
430*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	chdh;
431*7c478bd9Sstevel@tonic-gate 	char		*nameval;
432*7c478bd9Sstevel@tonic-gate 	char		classval[PICL_PROPNAMELEN_MAX];
433*7c478bd9Sstevel@tonic-gate 	int		err;
434*7c478bd9Sstevel@tonic-gate 	picl_prophdl_t	proph;
435*7c478bd9Sstevel@tonic-gate 	picl_propinfo_t	pinfo;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	/*
438*7c478bd9Sstevel@tonic-gate 	 * First get the class name of the node to compare with piclclass
439*7c478bd9Sstevel@tonic-gate 	 */
440*7c478bd9Sstevel@tonic-gate 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, classval,
441*7c478bd9Sstevel@tonic-gate 	    sizeof (classval));
442*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
443*7c478bd9Sstevel@tonic-gate 		print_errmsg(gettext(err_msg[EM_GETPVALBYNAME]),
444*7c478bd9Sstevel@tonic-gate 		    picl_strerror(err));
445*7c478bd9Sstevel@tonic-gate 		return (err);
446*7c478bd9Sstevel@tonic-gate 	}
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate #define	MATCHING_CLASSVAL(x, y)	((x == NULL) || (strcasecmp(x, y) == 0))
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	if (MATCHING_CLASSVAL(piclclass, classval)) {
451*7c478bd9Sstevel@tonic-gate 		err = picl_get_prop_by_name(nodeh, PICL_PROP_NAME, &proph);
452*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
453*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPROPBYNAME]),
454*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
455*7c478bd9Sstevel@tonic-gate 			return (err);
456*7c478bd9Sstevel@tonic-gate 		}
457*7c478bd9Sstevel@tonic-gate 
458*7c478bd9Sstevel@tonic-gate 		err = picl_get_propinfo(proph, &pinfo);
459*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
460*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPINFO]),
461*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
462*7c478bd9Sstevel@tonic-gate 			return (err);
463*7c478bd9Sstevel@tonic-gate 		}
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 		nameval = alloca(pinfo.size);
466*7c478bd9Sstevel@tonic-gate 		err = picl_get_propval(proph, nameval, pinfo.size);
467*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
468*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPVAL]),
469*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
470*7c478bd9Sstevel@tonic-gate 			return (err);
471*7c478bd9Sstevel@tonic-gate 		}
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 		(void) printf("%*s %s (%s, %" PRIxPICLHDL ")\n",
474*7c478bd9Sstevel@tonic-gate 		    NODEINFO_LEFT_MARGIN(lvl), " ", nameval, classval, nodeh);
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 		if (verbose_mode) {
477*7c478bd9Sstevel@tonic-gate 			err = print_proplist(lvl, nodeh);
478*7c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
479*7c478bd9Sstevel@tonic-gate 				return (err);
480*7c478bd9Sstevel@tonic-gate 		}
481*7c478bd9Sstevel@tonic-gate 		++lvl;
482*7c478bd9Sstevel@tonic-gate 	}
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate 	for (err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
485*7c478bd9Sstevel@tonic-gate 	    sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
486*7c478bd9Sstevel@tonic-gate 		err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
487*7c478bd9Sstevel@tonic-gate 		    sizeof (picl_nodehdl_t))) {
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
490*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPVALBYNAME]),
491*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
492*7c478bd9Sstevel@tonic-gate 			return (err);
493*7c478bd9Sstevel@tonic-gate 		}
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 		err = print_tree_by_class(lvl, chdh, piclclass);
496*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
497*7c478bd9Sstevel@tonic-gate 			return (err);
498*7c478bd9Sstevel@tonic-gate 	}
499*7c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
500*7c478bd9Sstevel@tonic-gate }
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate /*
504*7c478bd9Sstevel@tonic-gate  * This program prints the PICL tree.
505*7c478bd9Sstevel@tonic-gate  * If an invalid handle or stale handle is encountered while printing
506*7c478bd9Sstevel@tonic-gate  * the tree, it starts over from the root node.
507*7c478bd9Sstevel@tonic-gate  */
508*7c478bd9Sstevel@tonic-gate int
509*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
510*7c478bd9Sstevel@tonic-gate {
511*7c478bd9Sstevel@tonic-gate 	int		err;
512*7c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	rooth;
513*7c478bd9Sstevel@tonic-gate 	int		c;
514*7c478bd9Sstevel@tonic-gate 	int		done;
515*7c478bd9Sstevel@tonic-gate 	char		piclclass[PICL_CLASSNAMELEN_MAX];
516*7c478bd9Sstevel@tonic-gate 	int		cflg;
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
519*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 	if ((prog = strrchr(argv[0], '/')) == NULL)
522*7c478bd9Sstevel@tonic-gate 		prog = argv[0];
523*7c478bd9Sstevel@tonic-gate 	else
524*7c478bd9Sstevel@tonic-gate 		prog++;
525*7c478bd9Sstevel@tonic-gate 
526*7c478bd9Sstevel@tonic-gate 	cflg = 0;
527*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "vc:")) != EOF) {
528*7c478bd9Sstevel@tonic-gate 		switch (c) {
529*7c478bd9Sstevel@tonic-gate 		case 'v':
530*7c478bd9Sstevel@tonic-gate 			verbose_mode = 1;
531*7c478bd9Sstevel@tonic-gate 			break;
532*7c478bd9Sstevel@tonic-gate 		case 'c':
533*7c478bd9Sstevel@tonic-gate 			cflg = 1;
534*7c478bd9Sstevel@tonic-gate 			(void) strlcpy(piclclass, optarg,
535*7c478bd9Sstevel@tonic-gate 			    PICL_CLASSNAMELEN_MAX);
536*7c478bd9Sstevel@tonic-gate 			break;
537*7c478bd9Sstevel@tonic-gate 		case '?':
538*7c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
539*7c478bd9Sstevel@tonic-gate 		default:
540*7c478bd9Sstevel@tonic-gate 			usage();
541*7c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
542*7c478bd9Sstevel@tonic-gate 		}
543*7c478bd9Sstevel@tonic-gate 	}
544*7c478bd9Sstevel@tonic-gate 	if (optind != argc)
545*7c478bd9Sstevel@tonic-gate 		usage();
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	err = picl_initialize();
548*7c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
549*7c478bd9Sstevel@tonic-gate 		print_errmsg(gettext(err_msg[EM_INIT]), picl_strerror(err));
550*7c478bd9Sstevel@tonic-gate 		exit(1);
551*7c478bd9Sstevel@tonic-gate 	}
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 
554*7c478bd9Sstevel@tonic-gate 	do {
555*7c478bd9Sstevel@tonic-gate 		done = 1;
556*7c478bd9Sstevel@tonic-gate 		err = picl_get_root(&rooth);
557*7c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
558*7c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETROOT]),
559*7c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
560*7c478bd9Sstevel@tonic-gate 			exit(1);
561*7c478bd9Sstevel@tonic-gate 		}
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate 		err = print_tree_by_class(ROOT_LEVEL, rooth,
564*7c478bd9Sstevel@tonic-gate 		    (cflg ? piclclass : NULL));
565*7c478bd9Sstevel@tonic-gate 		if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
566*7c478bd9Sstevel@tonic-gate 			done = 0;
567*7c478bd9Sstevel@tonic-gate 	} while (!done);
568*7c478bd9Sstevel@tonic-gate 
569*7c478bd9Sstevel@tonic-gate 	(void) picl_shutdown();
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate 	return (0);
572*7c478bd9Sstevel@tonic-gate }
573