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