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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   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.
  12  *
  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]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 #include <stdio.h>
  29 #include <unistd.h>
  30 #include <strings.h>
  31 #include <libdevinfo.h>
  32 
  33 static void
  34 usage(void)
  35 {
  36         (void) fprintf(stderr,
  37             "Usage: devprop [-n device-path] "
  38             "[-vq] [-{b|i|l|s}] [property [...]]\n");
  39 }
  40 
  41 int
  42 main(int argc, char *argv[])
  43 {
  44         int c;
  45         boolean_t verbose = B_FALSE, quote = B_FALSE,
  46             error = B_FALSE;
  47         int type = DI_PROP_TYPE_UNKNOWN;
  48         char *path = "/";
  49         di_node_t dn;
  50         uchar_t *val_b;
  51         int *val_i;
  52         int64_t *val_l;
  53         char *val_s;
  54         int n;
  55 
  56         extern char *optarg;
  57         extern int optind;
  58 
  59 #define BOOL(ch, var)                           \
  60 case ch:                                        \
  61         var = B_TRUE;                           \
  62         break
  63 
  64 #define PER_OPT(ch, typ)                        \
  65 case ch:                                        \
  66         if (type != DI_PROP_TYPE_UNKNOWN) {     \
  67                 usage();                        \
  68                 return (1);                     \
  69         }                                       \
  70         type = (typ);                           \
  71         break
  72 
  73         while ((c = getopt(argc, argv, ":n:vqbils")) != -1) {
  74                 switch (c) {
  75                 case 'n':
  76                         path = optarg;
  77                         break;
  78                 case ':':
  79                         usage();
  80                         return (1);
  81 
  82                 BOOL('v', verbose);
  83                 BOOL('q', quote);
  84                 BOOL('?', error);
  85 
  86                 PER_OPT('b', DI_PROP_TYPE_BYTE);
  87                 PER_OPT('i', DI_PROP_TYPE_INT);
  88                 PER_OPT('l', DI_PROP_TYPE_INT64);
  89                 PER_OPT('s', DI_PROP_TYPE_STRING);
  90                 }
  91         }
  92 
  93 #undef  BOOL
  94 #undef  PER_OPT
  95 
  96         if (error) {
  97                 usage();
  98                 return (1);
  99         }
 100 
 101         /* default to strings */
 102         if (type == DI_PROP_TYPE_UNKNOWN)
 103                 type = DI_PROP_TYPE_STRING;
 104 
 105         /*
 106          * It's convenient to use the filesystem as a source of device
 107          * node paths.  In that case, the path will be prefixed with
 108          * "/devices", which we strip off here as di_init() expects
 109          * just the path to the node.
 110          */
 111         if (strncmp("/devices/", path, strlen("/devices/")) == 0)
 112                 path += strlen("/devices");
 113 
 114         if ((dn = di_init(path, DINFOPROP)) == DI_NODE_NIL) {
 115                 perror("di_init");
 116                 return (1);
 117         }
 118 
 119         /* Careful with that axe, Eugene... */
 120 #define PER_TYPE(typ, func, val, incr, form, pv, sep)   \
 121 case (typ):                                             \
 122         n = func(DDI_DEV_T_ANY,                         \
 123             dn, argv[optind], &(val));                      \
 124         while (n > 0) {                                      \
 125                 (void) printf((form), pv);              \
 126                 incr;                                   \
 127                 n--;                                    \
 128                 if (n > 0)                           \
 129                         (void) printf(sep);             \
 130         }                                               \
 131         (void) printf("\n");                            \
 132         break
 133 
 134         while (optind < argc) {
 135                 if (verbose)
 136                         (void) printf("%s=", argv[optind]);
 137 
 138                 switch (type) {
 139                 PER_TYPE(DI_PROP_TYPE_BYTE, di_prop_lookup_bytes,
 140                     val_b, val_b++, "%2.2x", *val_b, ".");
 141                 PER_TYPE(DI_PROP_TYPE_INT, di_prop_lookup_ints,
 142                     val_i, val_i++, "%8.8x", *val_i, ".");
 143                 PER_TYPE(DI_PROP_TYPE_INT64, di_prop_lookup_int64,
 144                     val_l, val_l++, "%16.16llx", *val_l, ".");
 145                 PER_TYPE(DI_PROP_TYPE_STRING, di_prop_lookup_strings,
 146                     val_s, val_s += strlen(val_s) + 1,
 147                     (quote ? "\"%s\"" : "%s"), val_s, " + ");
 148                 }
 149 
 150                 optind++;
 151         }
 152 
 153 #undef  PER_TYPE
 154 
 155         di_fini(dn);
 156 
 157         return (0);
 158 }