xref: /titanic_41/usr/src/cmd/picl/prtpicl/prtpicl.c (revision da6837b3e07c5c71f29c61ce60821868f9fc3102)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*da6837b3SJustin Frank  * Common Development and Distribution License (the "License").
6*da6837b3SJustin Frank  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*da6837b3SJustin Frank  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <stdarg.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <alloca.h>
317c478bd9Sstevel@tonic-gate #include <libintl.h>
327c478bd9Sstevel@tonic-gate #include <locale.h>
337c478bd9Sstevel@tonic-gate #include <unistd.h>
347c478bd9Sstevel@tonic-gate #include <assert.h>
357c478bd9Sstevel@tonic-gate #include <inttypes.h>
367c478bd9Sstevel@tonic-gate #include <sys/termios.h>
377c478bd9Sstevel@tonic-gate #include <picl.h>
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * Constant definitions and macros
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate #define	COL_DELIM		"|"
437c478bd9Sstevel@tonic-gate #define	ROOT_LEVEL		0
447c478bd9Sstevel@tonic-gate #define	LEVEL_INDENT		4
457c478bd9Sstevel@tonic-gate #define	PROP_INDENT		2
467c478bd9Sstevel@tonic-gate #define	NCOLS			80
477c478bd9Sstevel@tonic-gate #define	NODEINFO_LEFT_MARGIN(x)	(x * LEVEL_INDENT)
487c478bd9Sstevel@tonic-gate #define	PROPINFO_LEFT_MARGIN(x)	(x * LEVEL_INDENT + PROP_INDENT)
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #define	PRIxPICLTBL		PRIx64
517c478bd9Sstevel@tonic-gate #define	PRIxPICLHDL		PRIx64
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /*
547c478bd9Sstevel@tonic-gate  * Program variables
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate static	char	*prog;
577c478bd9Sstevel@tonic-gate static	int	verbose_mode = 0;
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate  * Error codes
617c478bd9Sstevel@tonic-gate  */
627c478bd9Sstevel@tonic-gate #define	EM_USAGE		0
637c478bd9Sstevel@tonic-gate #define	EM_INIT			1
647c478bd9Sstevel@tonic-gate #define	EM_GETROOT		2
657c478bd9Sstevel@tonic-gate #define	EM_GETPVAL		3
667c478bd9Sstevel@tonic-gate #define	EM_GETNXTBYCOL		4
677c478bd9Sstevel@tonic-gate #define	EM_GETNXTBYROW		5
687c478bd9Sstevel@tonic-gate #define	EM_GETPINFO		6
697c478bd9Sstevel@tonic-gate #define	EM_GETPVALBYNAME	7
707c478bd9Sstevel@tonic-gate #define	EM_GETPROPBYNAME	8
717c478bd9Sstevel@tonic-gate #define	EM_INT_INVSIZE		9
727c478bd9Sstevel@tonic-gate #define	EM_UINT_INVSIZE		10
737c478bd9Sstevel@tonic-gate #define	EM_FLOAT_INVSIZE	11
747c478bd9Sstevel@tonic-gate #define	EM_TS_INVALID		12
757c478bd9Sstevel@tonic-gate #define	EM_TABLE_INVSIZE	13
767c478bd9Sstevel@tonic-gate #define	EM_REF_INVSIZE		14
777c478bd9Sstevel@tonic-gate #define	EM_TYPE_UNKNOWN		15
787c478bd9Sstevel@tonic-gate #define	EM_TS_OVERFLOW		16
79*da6837b3SJustin Frank #define	EM_TS_INVSIZE		17
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate  * Error mesage texts
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate static	char	*err_msg[] = {
857c478bd9Sstevel@tonic-gate 	/* program usage */
867c478bd9Sstevel@tonic-gate 	"Usage: %s [-v] [-c <picl_class>]\n",			/*  0 */
877c478bd9Sstevel@tonic-gate 	/* picl call failed messages */
887c478bd9Sstevel@tonic-gate 	"picl_initialize failed: %s\n",				/*  1 */
897c478bd9Sstevel@tonic-gate 	"picl_get_root failed: %s\n",				/*  2 */
907c478bd9Sstevel@tonic-gate 	"picl_get_propval failed: %s\n",			/*  3 */
917c478bd9Sstevel@tonic-gate 	"picl_get_next_by_col failed: %s\n",			/*  4 */
927c478bd9Sstevel@tonic-gate 	"picl_get_next_by_row failed: %s\n",			/*  5 */
937c478bd9Sstevel@tonic-gate 	"picl_get_propinfo failed: %s\n",			/*  6 */
947c478bd9Sstevel@tonic-gate 	"picl_get_propval_by_name failed: %s\n",		/*  7 */
957c478bd9Sstevel@tonic-gate 	"picl_get_prop_by_name failed: %s\n",			/*  8 */
967c478bd9Sstevel@tonic-gate 	/* invalid data error messages */
977c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid int size %d\n",		/*  9 */
987c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid unsigned int size %d\n",	/* 10 */
997c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid float size %d\n",		/* 11 */
1007c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid timestamp\n",		/* 12 */
1017c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid table handle size %d\n",	/* 13 */
1027c478bd9Sstevel@tonic-gate 	"picl_get_propval: invalid reference size %d\n",	/* 14 */
1037c478bd9Sstevel@tonic-gate 	"picl_get_propval: unknown type\n",			/* 15 */
104*da6837b3SJustin Frank 	"picl_get_propval: timestamp value too large\n",	/* 16 */
105*da6837b3SJustin Frank 	"picl_get_propval: invalid timestamp size\n"		/* 17 */
1067c478bd9Sstevel@tonic-gate };
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1097c478bd9Sstevel@tonic-gate static void
print_errmsg(char * message,...)1107c478bd9Sstevel@tonic-gate print_errmsg(char *message, ...)
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate 	va_list ap;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	va_start(ap, message);
1157c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", prog);
1167c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, message, ap);
1177c478bd9Sstevel@tonic-gate 	va_end(ap);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate  * Print prtpicl usage
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate static void
usage(void)1247c478bd9Sstevel@tonic-gate usage(void)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate 	print_errmsg(gettext(err_msg[EM_USAGE]), prog);
1277c478bd9Sstevel@tonic-gate 	exit(1);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate /*
1317c478bd9Sstevel@tonic-gate  * print a bytearray value and format it to fit in 80 columns
1327c478bd9Sstevel@tonic-gate  */
1337c478bd9Sstevel@tonic-gate static void
print_bytearray(int lvl,uint8_t * vbuf,size_t nbytes)1347c478bd9Sstevel@tonic-gate print_bytearray(int lvl, uint8_t *vbuf, size_t nbytes)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	int		cnum;
1377c478bd9Sstevel@tonic-gate 	int		columns;
1387c478bd9Sstevel@tonic-gate 	char		*s;
1397c478bd9Sstevel@tonic-gate 	struct winsize	winsize;
1407c478bd9Sstevel@tonic-gate 	size_t		i;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	/*
1437c478bd9Sstevel@tonic-gate 	 * The COLUMNS_PER_BYTE is set to 4 to match the printf
1447c478bd9Sstevel@tonic-gate 	 * format used below, i.e. " %02x ", to print a byte
1457c478bd9Sstevel@tonic-gate 	 */
1467c478bd9Sstevel@tonic-gate #define	COLUMNS_PER_BYTE	4
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/*
1497c478bd9Sstevel@tonic-gate 	 * Kind of a hack to determine the width of the output...
1507c478bd9Sstevel@tonic-gate 	 */
1517c478bd9Sstevel@tonic-gate 	columns = NCOLS;
1527c478bd9Sstevel@tonic-gate 	if ((s = getenv("COLUMNS")) != NULL && (cnum = atoi(s)) > 0)
1537c478bd9Sstevel@tonic-gate 		columns = cnum;
1547c478bd9Sstevel@tonic-gate 	else if (isatty(fileno(stdout)) &&
1557c478bd9Sstevel@tonic-gate 	    ioctl(fileno(stdout), TIOCGWINSZ, &winsize) == 0 &&
1567c478bd9Sstevel@tonic-gate 	    winsize.ws_col != 0)
1577c478bd9Sstevel@tonic-gate 		columns = winsize.ws_col;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	cnum = PROPINFO_LEFT_MARGIN(lvl);
1617c478bd9Sstevel@tonic-gate 	if ((nbytes * COLUMNS_PER_BYTE + cnum) > columns) {
1627c478bd9Sstevel@tonic-gate 		(void) printf("\n");
1637c478bd9Sstevel@tonic-gate 		cnum = 0;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	for (i = 0; i < nbytes; ++i) {
1667c478bd9Sstevel@tonic-gate 		if (cnum > columns - COLUMNS_PER_BYTE) {
1677c478bd9Sstevel@tonic-gate 			(void) printf("\n");
1687c478bd9Sstevel@tonic-gate 			cnum = 0;
1697c478bd9Sstevel@tonic-gate 		}
1707c478bd9Sstevel@tonic-gate 		(void) printf(" %02x ", vbuf[i]);
1717c478bd9Sstevel@tonic-gate 		cnum += COLUMNS_PER_BYTE;
1727c478bd9Sstevel@tonic-gate 	}
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate /*
1767c478bd9Sstevel@tonic-gate  * Print a property's value
1777c478bd9Sstevel@tonic-gate  * If the property is read protected, return success.
1787c478bd9Sstevel@tonic-gate  * If an invalid/stale handle error is encountered, return the error. For
1797c478bd9Sstevel@tonic-gate  * other errors, print a message and return success.
1807c478bd9Sstevel@tonic-gate  */
1817c478bd9Sstevel@tonic-gate static int
print_propval(int lvl,picl_prophdl_t proph,const picl_propinfo_t * propinfo)1827c478bd9Sstevel@tonic-gate print_propval(int lvl, picl_prophdl_t proph, const picl_propinfo_t *propinfo)
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate 	int		err;
1857c478bd9Sstevel@tonic-gate 	void		*vbuf;
1867c478bd9Sstevel@tonic-gate 	char		*str;
1877c478bd9Sstevel@tonic-gate 	uint64_t	val64;
1887c478bd9Sstevel@tonic-gate 	time_t		tmp;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	/*
1917c478bd9Sstevel@tonic-gate 	 * If property is read protected, print a message and continue
1927c478bd9Sstevel@tonic-gate 	 */
1937c478bd9Sstevel@tonic-gate 	if (!(propinfo->accessmode & PICL_READ)) {
1947c478bd9Sstevel@tonic-gate 		(void) printf("<%s>", gettext("WRITE-ONLY"));
1957c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
1967c478bd9Sstevel@tonic-gate 	}
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	vbuf = alloca(propinfo->size);
1997c478bd9Sstevel@tonic-gate 	if (propinfo->type == PICL_PTYPE_VOID)
2007c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	err = picl_get_propval(proph, vbuf, propinfo->size);
2037c478bd9Sstevel@tonic-gate 	/*
2047c478bd9Sstevel@tonic-gate 	 * If the error is not a stale/invalid handle or noresponse, continue
2057c478bd9Sstevel@tonic-gate 	 * by ignoring the error/skipping the property.
2067c478bd9Sstevel@tonic-gate 	 */
2077c478bd9Sstevel@tonic-gate 	if ((err == PICL_INVALIDHANDLE) || (err == PICL_STALEHANDLE) ||
2087c478bd9Sstevel@tonic-gate 	    (err == PICL_NORESPONSE))
2097c478bd9Sstevel@tonic-gate 		return (err);
2107c478bd9Sstevel@tonic-gate 	else if (err != PICL_SUCCESS) {
2117c478bd9Sstevel@tonic-gate 		(void) printf("<%s: %s>", gettext("ERROR"), picl_strerror(err));
2127c478bd9Sstevel@tonic-gate 		return (PICL_SUCCESS);
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	switch (propinfo->type) {
2167c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_CHARSTRING:
217*da6837b3SJustin Frank 		if (propinfo->size > 0)
2187c478bd9Sstevel@tonic-gate 			(void) printf(" %s ", (char *)vbuf);
2197c478bd9Sstevel@tonic-gate 		break;
2207c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_INT:
2217c478bd9Sstevel@tonic-gate 		switch (propinfo->size) {
2227c478bd9Sstevel@tonic-gate 		case sizeof (int8_t):
2237c478bd9Sstevel@tonic-gate 			/* avoid using PRId8 until lint recognizes hh */
2247c478bd9Sstevel@tonic-gate 			(void) printf(" %d ", *(int8_t *)vbuf);
2257c478bd9Sstevel@tonic-gate 			break;
2267c478bd9Sstevel@tonic-gate 		case sizeof (int16_t):
2277c478bd9Sstevel@tonic-gate 			(void) printf(" %" PRId16 " ", *(int16_t *)vbuf);
2287c478bd9Sstevel@tonic-gate 			break;
2297c478bd9Sstevel@tonic-gate 		case sizeof (int32_t):
2307c478bd9Sstevel@tonic-gate 			(void) printf(" %" PRId32 " ", *(int32_t *)vbuf);
2317c478bd9Sstevel@tonic-gate 			break;
2327c478bd9Sstevel@tonic-gate 		case sizeof (int64_t):
2337c478bd9Sstevel@tonic-gate 			(void) printf(" %" PRId64 " ", *(int64_t *)vbuf);
2347c478bd9Sstevel@tonic-gate 			break;
2357c478bd9Sstevel@tonic-gate 		default:
2367c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_INT_INVSIZE]),
2377c478bd9Sstevel@tonic-gate 			    propinfo->size);
2387c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
2397c478bd9Sstevel@tonic-gate 		}
2407c478bd9Sstevel@tonic-gate 		break;
2417c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_UNSIGNED_INT:
2427c478bd9Sstevel@tonic-gate 		switch (propinfo->size) {
2437c478bd9Sstevel@tonic-gate 		case sizeof (uint8_t):
2447c478bd9Sstevel@tonic-gate 			/* avoid using PRIx8 until lint recognizes hh */
2457c478bd9Sstevel@tonic-gate 			(void) printf(" %#x ", *(uint8_t *)vbuf);
2467c478bd9Sstevel@tonic-gate 			break;
2477c478bd9Sstevel@tonic-gate 		case sizeof (uint16_t):
2487c478bd9Sstevel@tonic-gate 			(void) printf(" %#" PRIx16 " ", *(uint16_t *)vbuf);
2497c478bd9Sstevel@tonic-gate 			break;
2507c478bd9Sstevel@tonic-gate 		case sizeof (uint32_t):
2517c478bd9Sstevel@tonic-gate 			(void) printf(" %#" PRIx32 " ", *(uint32_t *)vbuf);
2527c478bd9Sstevel@tonic-gate 			break;
2537c478bd9Sstevel@tonic-gate 		case sizeof (uint64_t):
2547c478bd9Sstevel@tonic-gate 			(void) printf(" %#" PRIx64 " ", *(uint64_t *)vbuf);
2557c478bd9Sstevel@tonic-gate 			break;
2567c478bd9Sstevel@tonic-gate 		default:
2577c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_UINT_INVSIZE]),
2587c478bd9Sstevel@tonic-gate 			    propinfo->size);
2597c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
2607c478bd9Sstevel@tonic-gate 		}
2617c478bd9Sstevel@tonic-gate 		break;
2627c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_FLOAT:
2637c478bd9Sstevel@tonic-gate 		switch (propinfo->size) {
2647c478bd9Sstevel@tonic-gate 		case sizeof (float):
2657c478bd9Sstevel@tonic-gate 			(void) printf(" %f ", *(float *)vbuf);
2667c478bd9Sstevel@tonic-gate 			break;
2677c478bd9Sstevel@tonic-gate 		case sizeof (double):
2687c478bd9Sstevel@tonic-gate 			(void) printf(" %f ", *(double *)vbuf);
2697c478bd9Sstevel@tonic-gate 			break;
2707c478bd9Sstevel@tonic-gate 		default:
2717c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_FLOAT_INVSIZE]),
2727c478bd9Sstevel@tonic-gate 			    propinfo->size);
2737c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 		break;
2767c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_TIMESTAMP:
277*da6837b3SJustin Frank 		if (propinfo->size != sizeof (val64)) {
278*da6837b3SJustin Frank 			print_errmsg(gettext(err_msg[EM_TS_INVSIZE]));
279*da6837b3SJustin Frank 			return (PICL_FAILURE);
280*da6837b3SJustin Frank 		}
2817c478bd9Sstevel@tonic-gate 		val64 = *(uint64_t *)vbuf;
2827c478bd9Sstevel@tonic-gate 		tmp = (time_t)val64;
2837c478bd9Sstevel@tonic-gate 		if ((uint64_t)tmp != val64) {
2847c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_TS_OVERFLOW]));
2857c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
2867c478bd9Sstevel@tonic-gate 		}
2877c478bd9Sstevel@tonic-gate 		str = ctime(&tmp);
2887c478bd9Sstevel@tonic-gate 		if (str == NULL) {
2897c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_TS_INVALID]));
2907c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
2917c478bd9Sstevel@tonic-gate 		}
2927c478bd9Sstevel@tonic-gate 		str[strlen(str) - 1] = '\0';
2937c478bd9Sstevel@tonic-gate 		(void) printf(" %s ", str);
2947c478bd9Sstevel@tonic-gate 		break;
2957c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_TABLE:
2967c478bd9Sstevel@tonic-gate 		if (propinfo->size != sizeof (picl_prophdl_t)) {
2977c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_TABLE_INVSIZE]),
2987c478bd9Sstevel@tonic-gate 			    propinfo->size);
2997c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
3007c478bd9Sstevel@tonic-gate 		}
3017c478bd9Sstevel@tonic-gate 		(void) printf("(%" PRIxPICLTBL "TBL) ",
3027c478bd9Sstevel@tonic-gate 		    *(picl_prophdl_t *)vbuf);
3037c478bd9Sstevel@tonic-gate 		break;
3047c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_REFERENCE:
3057c478bd9Sstevel@tonic-gate 		if (propinfo->size != sizeof (picl_nodehdl_t)) {
3067c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_REF_INVSIZE]),
3077c478bd9Sstevel@tonic-gate 			    propinfo->size);
3087c478bd9Sstevel@tonic-gate 			return (PICL_FAILURE);
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 		(void) printf(" (%" PRIxPICLHDL "H) ", *(picl_nodehdl_t *)vbuf);
3117c478bd9Sstevel@tonic-gate 		break;
3127c478bd9Sstevel@tonic-gate 	case PICL_PTYPE_BYTEARRAY:
313*da6837b3SJustin Frank 		if (propinfo->size > 0)
3147c478bd9Sstevel@tonic-gate 			print_bytearray(lvl, vbuf, propinfo->size);
3157c478bd9Sstevel@tonic-gate 		break;
3167c478bd9Sstevel@tonic-gate 	default:
3177c478bd9Sstevel@tonic-gate 		print_errmsg(gettext(err_msg[EM_TYPE_UNKNOWN]));
3187c478bd9Sstevel@tonic-gate 		return (PICL_FAILURE);
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate /*
3247c478bd9Sstevel@tonic-gate  * print table property value
3257c478bd9Sstevel@tonic-gate  */
3267c478bd9Sstevel@tonic-gate static int
print_table_prop(int lvl,picl_prophdl_t tblh)3277c478bd9Sstevel@tonic-gate print_table_prop(int lvl, picl_prophdl_t tblh)
3287c478bd9Sstevel@tonic-gate {
3297c478bd9Sstevel@tonic-gate 	picl_prophdl_t	rowproph;
3307c478bd9Sstevel@tonic-gate 	picl_prophdl_t	colproph;
3317c478bd9Sstevel@tonic-gate 	int		err;
3327c478bd9Sstevel@tonic-gate 	picl_propinfo_t	propinfo;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	for (err = picl_get_next_by_col(tblh, &rowproph); err != PICL_ENDOFLIST;
3357c478bd9Sstevel@tonic-gate 	    err = picl_get_next_by_col(rowproph, &rowproph)) {
3367c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
3377c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETNXTBYCOL]),
3387c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
3397c478bd9Sstevel@tonic-gate 			return (err);
3407c478bd9Sstevel@tonic-gate 		}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 		(void) printf("%*s %s", PROPINFO_LEFT_MARGIN(lvl), " ",
3437c478bd9Sstevel@tonic-gate 		    COL_DELIM);
3447c478bd9Sstevel@tonic-gate 
3457c478bd9Sstevel@tonic-gate 		for (colproph = rowproph; err != PICL_ENDOFLIST;
3467c478bd9Sstevel@tonic-gate 		    err = picl_get_next_by_row(colproph, &colproph)) {
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
3497c478bd9Sstevel@tonic-gate 				print_errmsg(gettext(err_msg[EM_GETNXTBYROW]),
3507c478bd9Sstevel@tonic-gate 				    picl_strerror(err));
3517c478bd9Sstevel@tonic-gate 				return (err);
3527c478bd9Sstevel@tonic-gate 			}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 			err = picl_get_propinfo(colproph, &propinfo);
3557c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
3567c478bd9Sstevel@tonic-gate 				print_errmsg(gettext(err_msg[EM_GETPINFO]),
3577c478bd9Sstevel@tonic-gate 				    picl_strerror(err));
3587c478bd9Sstevel@tonic-gate 				return (err);
3597c478bd9Sstevel@tonic-gate 			}
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 			err = print_propval(lvl, colproph, &propinfo);
3627c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
3637c478bd9Sstevel@tonic-gate 				return (err);
3647c478bd9Sstevel@tonic-gate 			(void) printf(COL_DELIM);
3657c478bd9Sstevel@tonic-gate 		}
3667c478bd9Sstevel@tonic-gate 		(void) printf("\n");
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate /*
3727c478bd9Sstevel@tonic-gate  * Print the properties (name = value) of a node. If an error occurs
3737c478bd9Sstevel@tonic-gate  * when printing the property value, stop. print_propval() suppresses
3747c478bd9Sstevel@tonic-gate  * errors during getting property value except for stale/invalid handle
3757c478bd9Sstevel@tonic-gate  * and no response errors.
3767c478bd9Sstevel@tonic-gate  */
3777c478bd9Sstevel@tonic-gate static int
print_proplist(int lvl,picl_nodehdl_t nodeh)3787c478bd9Sstevel@tonic-gate print_proplist(int lvl, picl_nodehdl_t nodeh)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate 	int		err;
3817c478bd9Sstevel@tonic-gate 	picl_prophdl_t	proph;
3827c478bd9Sstevel@tonic-gate 	picl_propinfo_t	propinfo;
3837c478bd9Sstevel@tonic-gate 	picl_prophdl_t	tblh;
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	for (err = picl_get_first_prop(nodeh, &proph); err == PICL_SUCCESS;
3867c478bd9Sstevel@tonic-gate 	    err = picl_get_next_prop(proph, &proph)) {
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate 		err = picl_get_propinfo(proph, &propinfo);
3897c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
3907c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPINFO]),
3917c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
3927c478bd9Sstevel@tonic-gate 			return (err);
3937c478bd9Sstevel@tonic-gate 		}
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 		if (propinfo.type == PICL_PTYPE_VOID)
3967c478bd9Sstevel@tonic-gate 			(void) printf("%*s:%s\n", PROPINFO_LEFT_MARGIN(lvl),
3977c478bd9Sstevel@tonic-gate 			    " ", propinfo.name);
3987c478bd9Sstevel@tonic-gate 		else {
3997c478bd9Sstevel@tonic-gate 			(void) printf("%*s:%s\t", PROPINFO_LEFT_MARGIN(lvl),
4007c478bd9Sstevel@tonic-gate 			    " ", propinfo.name);
4017c478bd9Sstevel@tonic-gate 			err = print_propval(lvl, proph, &propinfo);
4027c478bd9Sstevel@tonic-gate 			(void) printf("\n");
4037c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
4047c478bd9Sstevel@tonic-gate 				return (err);
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 		/*
4087c478bd9Sstevel@tonic-gate 		 * Expand the table property
4097c478bd9Sstevel@tonic-gate 		 */
4107c478bd9Sstevel@tonic-gate 		if (propinfo.type == PICL_PTYPE_TABLE) {
4117c478bd9Sstevel@tonic-gate 			err = picl_get_propval(proph, &tblh, propinfo.size);
4127c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS) {
4137c478bd9Sstevel@tonic-gate 				print_errmsg(gettext(err_msg[EM_GETPVAL]),
4147c478bd9Sstevel@tonic-gate 				    picl_strerror(err));
4157c478bd9Sstevel@tonic-gate 				return (err);
4167c478bd9Sstevel@tonic-gate 			}
4177c478bd9Sstevel@tonic-gate 			err = print_table_prop(lvl, tblh);
4187c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
4197c478bd9Sstevel@tonic-gate 				return (err);
4207c478bd9Sstevel@tonic-gate 		}
4217c478bd9Sstevel@tonic-gate 	}
4227c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate  * Recursively print the PICL tree
4277c478bd9Sstevel@tonic-gate  * When piclclass is specified, print only the nodes of that class.
4287c478bd9Sstevel@tonic-gate  */
4297c478bd9Sstevel@tonic-gate static int
print_tree_by_class(int lvl,picl_nodehdl_t nodeh,char * piclclass)4307c478bd9Sstevel@tonic-gate print_tree_by_class(int lvl, picl_nodehdl_t nodeh, char *piclclass)
4317c478bd9Sstevel@tonic-gate {
4327c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	chdh;
4337c478bd9Sstevel@tonic-gate 	char		*nameval;
4347c478bd9Sstevel@tonic-gate 	char		classval[PICL_PROPNAMELEN_MAX];
4357c478bd9Sstevel@tonic-gate 	int		err;
4367c478bd9Sstevel@tonic-gate 	picl_prophdl_t	proph;
4377c478bd9Sstevel@tonic-gate 	picl_propinfo_t	pinfo;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	/*
4407c478bd9Sstevel@tonic-gate 	 * First get the class name of the node to compare with piclclass
4417c478bd9Sstevel@tonic-gate 	 */
4427c478bd9Sstevel@tonic-gate 	err = picl_get_propval_by_name(nodeh, PICL_PROP_CLASSNAME, classval,
4437c478bd9Sstevel@tonic-gate 	    sizeof (classval));
4447c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
4457c478bd9Sstevel@tonic-gate 		print_errmsg(gettext(err_msg[EM_GETPVALBYNAME]),
4467c478bd9Sstevel@tonic-gate 		    picl_strerror(err));
4477c478bd9Sstevel@tonic-gate 		return (err);
4487c478bd9Sstevel@tonic-gate 	}
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate #define	MATCHING_CLASSVAL(x, y)	((x == NULL) || (strcasecmp(x, y) == 0))
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	if (MATCHING_CLASSVAL(piclclass, classval)) {
4537c478bd9Sstevel@tonic-gate 		err = picl_get_prop_by_name(nodeh, PICL_PROP_NAME, &proph);
4547c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
4557c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPROPBYNAME]),
4567c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
4577c478bd9Sstevel@tonic-gate 			return (err);
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		err = picl_get_propinfo(proph, &pinfo);
4617c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
4627c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPINFO]),
4637c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
4647c478bd9Sstevel@tonic-gate 			return (err);
4657c478bd9Sstevel@tonic-gate 		}
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 		nameval = alloca(pinfo.size);
4687c478bd9Sstevel@tonic-gate 		err = picl_get_propval(proph, nameval, pinfo.size);
4697c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
4707c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPVAL]),
4717c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
4727c478bd9Sstevel@tonic-gate 			return (err);
4737c478bd9Sstevel@tonic-gate 		}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		(void) printf("%*s %s (%s, %" PRIxPICLHDL ")\n",
4767c478bd9Sstevel@tonic-gate 		    NODEINFO_LEFT_MARGIN(lvl), " ", nameval, classval, nodeh);
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		if (verbose_mode) {
4797c478bd9Sstevel@tonic-gate 			err = print_proplist(lvl, nodeh);
4807c478bd9Sstevel@tonic-gate 			if (err != PICL_SUCCESS)
4817c478bd9Sstevel@tonic-gate 				return (err);
4827c478bd9Sstevel@tonic-gate 		}
4837c478bd9Sstevel@tonic-gate 		++lvl;
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	for (err = picl_get_propval_by_name(nodeh, PICL_PROP_CHILD, &chdh,
4877c478bd9Sstevel@tonic-gate 	    sizeof (picl_nodehdl_t)); err != PICL_PROPNOTFOUND;
4887c478bd9Sstevel@tonic-gate 	    err = picl_get_propval_by_name(chdh, PICL_PROP_PEER, &chdh,
4897c478bd9Sstevel@tonic-gate 	    sizeof (picl_nodehdl_t))) {
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
4927c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETPVALBYNAME]),
4937c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
4947c478bd9Sstevel@tonic-gate 			return (err);
4957c478bd9Sstevel@tonic-gate 		}
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 		err = print_tree_by_class(lvl, chdh, piclclass);
4987c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS)
4997c478bd9Sstevel@tonic-gate 			return (err);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 	return (PICL_SUCCESS);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate  * This program prints the PICL tree.
5077c478bd9Sstevel@tonic-gate  * If an invalid handle or stale handle is encountered while printing
5087c478bd9Sstevel@tonic-gate  * the tree, it starts over from the root node.
5097c478bd9Sstevel@tonic-gate  */
5107c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)5117c478bd9Sstevel@tonic-gate main(int argc, char **argv)
5127c478bd9Sstevel@tonic-gate {
5137c478bd9Sstevel@tonic-gate 	int		err;
5147c478bd9Sstevel@tonic-gate 	picl_nodehdl_t	rooth;
5157c478bd9Sstevel@tonic-gate 	int		c;
5167c478bd9Sstevel@tonic-gate 	int		done;
5177c478bd9Sstevel@tonic-gate 	char		piclclass[PICL_CLASSNAMELEN_MAX];
5187c478bd9Sstevel@tonic-gate 	int		cflg;
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
5217c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	if ((prog = strrchr(argv[0], '/')) == NULL)
5247c478bd9Sstevel@tonic-gate 		prog = argv[0];
5257c478bd9Sstevel@tonic-gate 	else
5267c478bd9Sstevel@tonic-gate 		prog++;
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	cflg = 0;
5297c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "vc:")) != EOF) {
5307c478bd9Sstevel@tonic-gate 		switch (c) {
5317c478bd9Sstevel@tonic-gate 		case 'v':
5327c478bd9Sstevel@tonic-gate 			verbose_mode = 1;
5337c478bd9Sstevel@tonic-gate 			break;
5347c478bd9Sstevel@tonic-gate 		case 'c':
5357c478bd9Sstevel@tonic-gate 			cflg = 1;
5367c478bd9Sstevel@tonic-gate 			(void) strlcpy(piclclass, optarg,
5377c478bd9Sstevel@tonic-gate 			    PICL_CLASSNAMELEN_MAX);
5387c478bd9Sstevel@tonic-gate 			break;
5397c478bd9Sstevel@tonic-gate 		case '?':
5407c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
5417c478bd9Sstevel@tonic-gate 		default:
5427c478bd9Sstevel@tonic-gate 			usage();
5437c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
5447c478bd9Sstevel@tonic-gate 		}
5457c478bd9Sstevel@tonic-gate 	}
5467c478bd9Sstevel@tonic-gate 	if (optind != argc)
5477c478bd9Sstevel@tonic-gate 		usage();
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 	err = picl_initialize();
5507c478bd9Sstevel@tonic-gate 	if (err != PICL_SUCCESS) {
5517c478bd9Sstevel@tonic-gate 		print_errmsg(gettext(err_msg[EM_INIT]), picl_strerror(err));
5527c478bd9Sstevel@tonic-gate 		exit(1);
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 	do {
5577c478bd9Sstevel@tonic-gate 		done = 1;
5587c478bd9Sstevel@tonic-gate 		err = picl_get_root(&rooth);
5597c478bd9Sstevel@tonic-gate 		if (err != PICL_SUCCESS) {
5607c478bd9Sstevel@tonic-gate 			print_errmsg(gettext(err_msg[EM_GETROOT]),
5617c478bd9Sstevel@tonic-gate 			    picl_strerror(err));
5627c478bd9Sstevel@tonic-gate 			exit(1);
5637c478bd9Sstevel@tonic-gate 		}
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 		err = print_tree_by_class(ROOT_LEVEL, rooth,
5667c478bd9Sstevel@tonic-gate 		    (cflg ? piclclass : NULL));
5677c478bd9Sstevel@tonic-gate 		if ((err == PICL_STALEHANDLE) || (err == PICL_INVALIDHANDLE))
5687c478bd9Sstevel@tonic-gate 			done = 0;
5697c478bd9Sstevel@tonic-gate 	} while (!done);
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	(void) picl_shutdown();
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	return (0);
5747c478bd9Sstevel@tonic-gate }
575