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