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 
  27 #include <stdio.h>
  28 #include <unistd.h>
  29 #include <strings.h>
  30 #include <libdevinfo.h>
  31 
  32 static void
  33 usage(void)
  34 {
  35         (void) fprintf(stderr,
  36             "Usage: devprop [-n device-path] "
  37             "[-vq] [-{b|i|l|s}] [property [...]]\n");
  38 }
  39 
  40 int
  41 main(int argc, char *argv[])
  42 {
  43         int c;
  44         boolean_t verbose = B_FALSE, quote = B_FALSE,
  45             error = B_FALSE;
  46         int type = DI_PROP_TYPE_UNKNOWN;
  47         char *path = "/";
  48         di_node_t dn;
  49         uchar_t *val_b;
  50         int *val_i;
  51         int64_t *val_l;
  52         char *val_s, *ptr;
  53         int n;
  54 
  55         extern char *optarg;
  56         extern int optind;
  57 
  58 #define BOOL(ch, var)                           \
  59 case ch:                                        \
  60         var = B_TRUE;                           \
  61         break
  62 
  63 #define PER_OPT(ch, typ)                        \
  64 case ch:                                        \
  65         if (type != DI_PROP_TYPE_UNKNOWN) {     \
  66                 usage();                        \
  67                 return (1);                     \
  68         }                                       \
  69         type = (typ);                           \
  70         break
  71 
  72         while ((c = getopt(argc, argv, ":n:vqbils")) != -1) {
  73                 switch (c) {
  74                 case 'n':
  75                         if ((path = realpath(optarg, NULL)) == NULL)
  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                 /* cut off minor name */
 115                 if ((ptr = strrchr(path, ':')) != NULL)
 116                         *ptr = '\0';
 117         }
 118 
 119         if ((dn = di_init(path, DINFOPROP)) == DI_NODE_NIL) {
 120                 perror("di_init");
 121                 return (1);
 122         }
 123 
 124         /* Careful with that axe, Eugene... */
 125 #define PER_TYPE(typ, func, val, incr, form, pv, sep)   \
 126 case (typ):                                             \
 127         n = func(DDI_DEV_T_ANY,                         \
 128             dn, argv[optind], &(val));                      \
 129         while (n > 0) {                                      \
 130                 (void) printf((form), pv);              \
 131                 incr;                                   \
 132                 n--;                                    \
 133                 if (n > 0)                           \
 134                         (void) printf(sep);             \
 135         }                                               \
 136         (void) printf("\n");                            \
 137         break
 138 
 139         while (optind < argc) {
 140                 if (verbose)
 141                         (void) printf("%s=", argv[optind]);
 142 
 143                 switch (type) {
 144                 PER_TYPE(DI_PROP_TYPE_BYTE, di_prop_lookup_bytes,
 145                     val_b, val_b++, "%2.2x", *val_b, ".");
 146                 PER_TYPE(DI_PROP_TYPE_INT, di_prop_lookup_ints,
 147                     val_i, val_i++, "%8.8x", *val_i, ".");
 148                 PER_TYPE(DI_PROP_TYPE_INT64, di_prop_lookup_int64,
 149                     val_l, val_l++, "%16.16llx", *val_l, ".");
 150                 PER_TYPE(DI_PROP_TYPE_STRING, di_prop_lookup_strings,
 151                     val_s, val_s += strlen(val_s) + 1,
 152                     (quote ? "\"%s\"" : "%s"), val_s, " + ");
 153                 }
 154 
 155                 optind++;
 156         }
 157 
 158 #undef  PER_TYPE
 159 
 160         di_fini(dn);
 161 
 162         return (0);
 163 }