4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
36 #include <sys/termios.h>
40 * Constant definitions and macros
44 #define LEVEL_INDENT 4
47 #define NODEINFO_LEFT_MARGIN(x) (x * LEVEL_INDENT)
48 #define PROPINFO_LEFT_MARGIN(x) (x * LEVEL_INDENT + PROP_INDENT)
50 #define PRIxPICLTBL PRIx64
51 #define PRIxPICLHDL PRIx64
57 static int verbose_mode
= 0;
66 #define EM_GETNXTBYCOL 4
67 #define EM_GETNXTBYROW 5
69 #define EM_GETPVALBYNAME 7
70 #define EM_GETPROPBYNAME 8
71 #define EM_INT_INVSIZE 9
72 #define EM_UINT_INVSIZE 10
73 #define EM_FLOAT_INVSIZE 11
74 #define EM_TS_INVALID 12
75 #define EM_TABLE_INVSIZE 13
76 #define EM_REF_INVSIZE 14
77 #define EM_TYPE_UNKNOWN 15
78 #define EM_TS_OVERFLOW 16
79 #define EM_TS_INVSIZE 17
84 static char *err_msg
[] = {
86 "Usage: %s [-v] [-c <picl_class>]\n", /* 0 */
87 /* picl call failed messages */
88 "picl_initialize failed: %s\n", /* 1 */
89 "picl_get_root failed: %s\n", /* 2 */
90 "picl_get_propval failed: %s\n", /* 3 */
91 "picl_get_next_by_col failed: %s\n", /* 4 */
92 "picl_get_next_by_row failed: %s\n", /* 5 */
93 "picl_get_propinfo failed: %s\n", /* 6 */
94 "picl_get_propval_by_name failed: %s\n", /* 7 */
95 "picl_get_prop_by_name failed: %s\n", /* 8 */
96 /* invalid data error messages */
97 "picl_get_propval: invalid int size %d\n", /* 9 */
98 "picl_get_propval: invalid unsigned int size %d\n", /* 10 */
99 "picl_get_propval: invalid float size %d\n", /* 11 */
100 "picl_get_propval: invalid timestamp\n", /* 12 */
101 "picl_get_propval: invalid table handle size %d\n", /* 13 */
102 "picl_get_propval: invalid reference size %d\n", /* 14 */
103 "picl_get_propval: unknown type\n", /* 15 */
104 "picl_get_propval: timestamp value too large\n", /* 16 */
105 "picl_get_propval: invalid timestamp size\n" /* 17 */
110 print_errmsg(char *message
, ...)
114 va_start(ap
, message
);
115 (void) fprintf(stderr
, "%s: ", prog
);
116 (void) vfprintf(stderr
, message
, ap
);
121 * Print prtpicl usage
126 print_errmsg(gettext(err_msg
[EM_USAGE
]), prog
);
131 * print a bytearray value and format it to fit in 80 columns
134 print_bytearray(int lvl
, uint8_t *vbuf
, size_t nbytes
)
139 struct winsize winsize
;
143 * The COLUMNS_PER_BYTE is set to 4 to match the printf
144 * format used below, i.e. " %02x ", to print a byte
146 #define COLUMNS_PER_BYTE 4
149 * Kind of a hack to determine the width of the output...
152 if ((s
= getenv("COLUMNS")) != NULL
&& (cnum
= atoi(s
)) > 0)
154 else if (isatty(fileno(stdout
)) &&
155 ioctl(fileno(stdout
), TIOCGWINSZ
, &winsize
) == 0 &&
157 columns
= winsize
.ws_col
;
160 cnum
= PROPINFO_LEFT_MARGIN(lvl
);
161 if ((nbytes
* COLUMNS_PER_BYTE
+ cnum
) > columns
) {
165 for (i
= 0; i
< nbytes
; ++i
) {
166 if (cnum
> columns
- COLUMNS_PER_BYTE
) {
170 (void) printf(" %02x ", vbuf
[i
]);
171 cnum
+= COLUMNS_PER_BYTE
;
176 * Print a property's value
177 * If the property is read protected, return success.
178 * If an invalid/stale handle error is encountered, return the error. For
179 * other errors, print a message and return success.
182 print_propval(int lvl
, picl_prophdl_t proph
, const picl_propinfo_t
*propinfo
)
191 * If property is read protected, print a message and continue
193 if (!(propinfo
->accessmode
& PICL_READ
)) {
194 (void) printf("<%s>", gettext("WRITE-ONLY"));
195 return (PICL_SUCCESS
);
198 vbuf
= alloca(propinfo
->size
);
199 if (propinfo
->type
== PICL_PTYPE_VOID
)
200 return (PICL_SUCCESS
);
202 err
= picl_get_propval(proph
, vbuf
, propinfo
->size
);
204 * If the error is not a stale/invalid handle or noresponse, continue
205 * by ignoring the error/skipping the property.
207 if ((err
== PICL_INVALIDHANDLE
) || (err
== PICL_STALEHANDLE
) ||
208 (err
== PICL_NORESPONSE
))
210 else if (err
!= PICL_SUCCESS
) {
211 (void) printf("<%s: %s>", gettext("ERROR"), picl_strerror(err
));
212 return (PICL_SUCCESS
);
215 switch (propinfo
->type
) {
216 case PICL_PTYPE_CHARSTRING
:
217 if (propinfo
->size
> 0)
218 (void) printf(" %s ", (char *)vbuf
);
221 switch (propinfo
->size
) {
222 case sizeof (int8_t):
223 /* avoid using PRId8 until lint recognizes hh */
224 (void) printf(" %d ", *(int8_t *)vbuf
);
226 case sizeof (int16_t):
227 (void) printf(" %" PRId16
" ", *(int16_t *)vbuf
);
229 case sizeof (int32_t):
230 (void) printf(" %" PRId32
" ", *(int32_t *)vbuf
);
232 case sizeof (int64_t):
233 (void) printf(" %" PRId64
" ", *(int64_t *)vbuf
);
236 print_errmsg(gettext(err_msg
[EM_INT_INVSIZE
]),
238 return (PICL_FAILURE
);
241 case PICL_PTYPE_UNSIGNED_INT
:
242 switch (propinfo
->size
) {
243 case sizeof (uint8_t):
244 /* avoid using PRIx8 until lint recognizes hh */
245 (void) printf(" %#x ", *(uint8_t *)vbuf
);
247 case sizeof (uint16_t):
248 (void) printf(" %#" PRIx16
" ", *(uint16_t *)vbuf
);
250 case sizeof (uint32_t):
251 (void) printf(" %#" PRIx32
" ", *(uint32_t *)vbuf
);
253 case sizeof (uint64_t):
254 (void) printf(" %#" PRIx64
" ", *(uint64_t *)vbuf
);
257 print_errmsg(gettext(err_msg
[EM_UINT_INVSIZE
]),
259 return (PICL_FAILURE
);
262 case PICL_PTYPE_FLOAT
:
263 switch (propinfo
->size
) {
265 (void) printf(" %f ", *(float *)vbuf
);
267 case sizeof (double):
268 (void) printf(" %f ", *(double *)vbuf
);
271 print_errmsg(gettext(err_msg
[EM_FLOAT_INVSIZE
]),
273 return (PICL_FAILURE
);
276 case PICL_PTYPE_TIMESTAMP
:
277 if (propinfo
->size
!= sizeof (val64
)) {
278 print_errmsg(gettext(err_msg
[EM_TS_INVSIZE
]));
279 return (PICL_FAILURE
);
281 val64
= *(uint64_t *)vbuf
;
283 if ((uint64_t)tmp
!= val64
) {
284 print_errmsg(gettext(err_msg
[EM_TS_OVERFLOW
]));
285 return (PICL_FAILURE
);
289 print_errmsg(gettext(err_msg
[EM_TS_INVALID
]));
290 return (PICL_FAILURE
);
292 str
[strlen(str
) - 1] = '\0';
293 (void) printf(" %s ", str
);
295 case PICL_PTYPE_TABLE
:
296 if (propinfo
->size
!= sizeof (picl_prophdl_t
)) {
297 print_errmsg(gettext(err_msg
[EM_TABLE_INVSIZE
]),
299 return (PICL_FAILURE
);
301 (void) printf("(%" PRIxPICLTBL
"TBL) ",
302 *(picl_prophdl_t
*)vbuf
);
304 case PICL_PTYPE_REFERENCE
:
305 if (propinfo
->size
!= sizeof (picl_nodehdl_t
)) {
306 print_errmsg(gettext(err_msg
[EM_REF_INVSIZE
]),
308 return (PICL_FAILURE
);
310 (void) printf(" (%" PRIxPICLHDL
"H) ", *(picl_nodehdl_t
*)vbuf
);
312 case PICL_PTYPE_BYTEARRAY
:
313 if (propinfo
->size
> 0)
314 print_bytearray(lvl
, vbuf
, propinfo
->size
);
317 print_errmsg(gettext(err_msg
[EM_TYPE_UNKNOWN
]));
318 return (PICL_FAILURE
);
320 return (PICL_SUCCESS
);
324 * print table property value
327 print_table_prop(int lvl
, picl_prophdl_t tblh
)
329 picl_prophdl_t rowproph
;
330 picl_prophdl_t colproph
;
332 picl_propinfo_t propinfo
;
334 for (err
= picl_get_next_by_col(tblh
, &rowproph
); err
!= PICL_ENDOFLIST
;
335 err
= picl_get_next_by_col(rowproph
, &rowproph
)) {
336 if (err
!= PICL_SUCCESS
) {
337 print_errmsg(gettext(err_msg
[EM_GETNXTBYCOL
]),
342 (void) printf("%*s %s", PROPINFO_LEFT_MARGIN(lvl
), " ",
345 for (colproph
= rowproph
; err
!= PICL_ENDOFLIST
;
346 err
= picl_get_next_by_row(colproph
, &colproph
)) {
348 if (err
!= PICL_SUCCESS
) {
349 print_errmsg(gettext(err_msg
[EM_GETNXTBYROW
]),
354 err
= picl_get_propinfo(colproph
, &propinfo
);
355 if (err
!= PICL_SUCCESS
) {
356 print_errmsg(gettext(err_msg
[EM_GETPINFO
]),
361 err
= print_propval(lvl
, colproph
, &propinfo
);
362 if (err
!= PICL_SUCCESS
)
364 (void) printf(COL_DELIM
);
368 return (PICL_SUCCESS
);
372 * Print the properties (name = value) of a node. If an error occurs
373 * when printing the property value, stop. print_propval() suppresses
374 * errors during getting property value except for stale/invalid handle
375 * and no response errors.
378 print_proplist(int lvl
, picl_nodehdl_t nodeh
)
381 picl_prophdl_t proph
;
382 picl_propinfo_t propinfo
;
385 for (err
= picl_get_first_prop(nodeh
, &proph
); err
== PICL_SUCCESS
;
386 err
= picl_get_next_prop(proph
, &proph
)) {
388 err
= picl_get_propinfo(proph
, &propinfo
);
389 if (err
!= PICL_SUCCESS
) {
390 print_errmsg(gettext(err_msg
[EM_GETPINFO
]),
395 if (propinfo
.type
== PICL_PTYPE_VOID
)
396 (void) printf("%*s:%s\n", PROPINFO_LEFT_MARGIN(lvl
),
399 (void) printf("%*s:%s\t", PROPINFO_LEFT_MARGIN(lvl
),
401 err
= print_propval(lvl
, proph
, &propinfo
);
403 if (err
!= PICL_SUCCESS
)
408 * Expand the table property
410 if (propinfo
.type
== PICL_PTYPE_TABLE
) {
411 err
= picl_get_propval(proph
, &tblh
, propinfo
.size
);
412 if (err
!= PICL_SUCCESS
) {
413 print_errmsg(gettext(err_msg
[EM_GETPVAL
]),
417 err
= print_table_prop(lvl
, tblh
);
418 if (err
!= PICL_SUCCESS
)
422 return (PICL_SUCCESS
);
426 * Recursively print the PICL tree
427 * When piclclass is specified, print only the nodes of that class.
430 print_tree_by_class(int lvl
, picl_nodehdl_t nodeh
, char *piclclass
)
434 char classval
[PICL_PROPNAMELEN_MAX
];
436 picl_prophdl_t proph
;
437 picl_propinfo_t pinfo
;
440 * First get the class name of the node to compare with piclclass
442 err
= picl_get_propval_by_name(nodeh
, PICL_PROP_CLASSNAME
, classval
,
444 if (err
!= PICL_SUCCESS
) {
445 print_errmsg(gettext(err_msg
[EM_GETPVALBYNAME
]),
450 #define MATCHING_CLASSVAL(x, y) ((x == NULL) || (strcasecmp(x, y) == 0))
452 if (MATCHING_CLASSVAL(piclclass
, classval
)) {
453 err
= picl_get_prop_by_name(nodeh
, PICL_PROP_NAME
, &proph
);
454 if (err
!= PICL_SUCCESS
) {
455 print_errmsg(gettext(err_msg
[EM_GETPROPBYNAME
]),
460 err
= picl_get_propinfo(proph
, &pinfo
);
461 if (err
!= PICL_SUCCESS
) {
462 print_errmsg(gettext(err_msg
[EM_GETPINFO
]),
467 nameval
= alloca(pinfo
.size
);
468 err
= picl_get_propval(proph
, nameval
, pinfo
.size
);
469 if (err
!= PICL_SUCCESS
) {
470 print_errmsg(gettext(err_msg
[EM_GETPVAL
]),
475 (void) printf("%*s %s (%s, %" PRIxPICLHDL
")\n",
476 NODEINFO_LEFT_MARGIN(lvl
), " ", nameval
, classval
, nodeh
);
479 err
= print_proplist(lvl
, nodeh
);
480 if (err
!= PICL_SUCCESS
)
486 for (err
= picl_get_propval_by_name(nodeh
, PICL_PROP_CHILD
, &chdh
,
487 sizeof (picl_nodehdl_t
)); err
!= PICL_PROPNOTFOUND
;
488 err
= picl_get_propval_by_name(chdh
, PICL_PROP_PEER
, &chdh
,
489 sizeof (picl_nodehdl_t
))) {
491 if (err
!= PICL_SUCCESS
) {
492 print_errmsg(gettext(err_msg
[EM_GETPVALBYNAME
]),
497 err
= print_tree_by_class(lvl
, chdh
, piclclass
);
498 if (err
!= PICL_SUCCESS
)
501 return (PICL_SUCCESS
);
506 * This program prints the PICL tree.
507 * If an invalid handle or stale handle is encountered while printing
508 * the tree, it starts over from the root node.
511 main(int argc
, char **argv
)
514 picl_nodehdl_t rooth
;
517 char piclclass
[PICL_CLASSNAMELEN_MAX
];
520 (void) setlocale(LC_ALL
, "");
521 (void) textdomain(TEXT_DOMAIN
);
523 if ((prog
= strrchr(argv
[0], '/')) == NULL
)
529 while ((c
= getopt(argc
, argv
, "vc:")) != EOF
) {
536 (void) strlcpy(piclclass
, optarg
,
537 PICL_CLASSNAMELEN_MAX
);
549 err
= picl_initialize();
550 if (err
!= PICL_SUCCESS
) {
551 print_errmsg(gettext(err_msg
[EM_INIT
]), picl_strerror(err
));
558 err
= picl_get_root(&rooth
);
559 if (err
!= PICL_SUCCESS
) {
560 print_errmsg(gettext(err_msg
[EM_GETROOT
]),
565 err
= print_tree_by_class(ROOT_LEVEL
, rooth
,
566 (cflg
? piclclass
: NULL
));
567 if ((err
== PICL_STALEHANDLE
) || (err
== PICL_INVALIDHANDLE
))
571 (void) picl_shutdown();