1*26947304SEvan Yan /* 2*26947304SEvan Yan * CDDL HEADER START 3*26947304SEvan Yan * 4*26947304SEvan Yan * The contents of this file are subject to the terms of the 5*26947304SEvan Yan * Common Development and Distribution License (the "License"). 6*26947304SEvan Yan * You may not use this file except in compliance with the License. 7*26947304SEvan Yan * 8*26947304SEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*26947304SEvan Yan * or http://www.opensolaris.org/os/licensing. 10*26947304SEvan Yan * See the License for the specific language governing permissions 11*26947304SEvan Yan * and limitations under the License. 12*26947304SEvan Yan * 13*26947304SEvan Yan * When distributing Covered Code, include this CDDL HEADER in each 14*26947304SEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*26947304SEvan Yan * If applicable, add the following below this CDDL HEADER, with the 16*26947304SEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying 17*26947304SEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner] 18*26947304SEvan Yan * 19*26947304SEvan Yan * CDDL HEADER END 20*26947304SEvan Yan */ 21*26947304SEvan Yan /* 22*26947304SEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23*26947304SEvan Yan * Use is subject to license terms. 24*26947304SEvan Yan */ 25*26947304SEvan Yan 26*26947304SEvan Yan #include <stdio.h> 27*26947304SEvan Yan #include <stdlib.h> 28*26947304SEvan Yan #include <string.h> 29*26947304SEvan Yan #include <locale.h> 30*26947304SEvan Yan #include <libintl.h> 31*26947304SEvan Yan #include <alloca.h> 32*26947304SEvan Yan #include <getopt.h> 33*26947304SEvan Yan #include <libhotplug.h> 34*26947304SEvan Yan #include <sys/types.h> 35*26947304SEvan Yan #include <sys/sunddi.h> 36*26947304SEvan Yan #include <sys/ddi_hp.h> 37*26947304SEvan Yan 38*26947304SEvan Yan #if !defined(TEXT_DOMAIN) /* should be defined by cc -D */ 39*26947304SEvan Yan #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */ 40*26947304SEvan Yan #endif 41*26947304SEvan Yan 42*26947304SEvan Yan /* 43*26947304SEvan Yan * Function prototypes. 44*26947304SEvan Yan */ 45*26947304SEvan Yan static int cmd_list(int, char **, const char *); 46*26947304SEvan Yan static int cmd_online(int, char **, const char *); 47*26947304SEvan Yan static int cmd_offline(int, char **, const char *); 48*26947304SEvan Yan static int cmd_enable(int, char **, const char *); 49*26947304SEvan Yan static int cmd_disable(int, char **, const char *); 50*26947304SEvan Yan static int cmd_poweron(int, char **, const char *); 51*26947304SEvan Yan static int cmd_poweroff(int, char **, const char *); 52*26947304SEvan Yan static int cmd_getpriv(int, char **, const char *); 53*26947304SEvan Yan static int cmd_setpriv(int, char **, const char *); 54*26947304SEvan Yan static int cmd_changestate(int, char **, const char *); 55*26947304SEvan Yan static void parse_common(int, char **, const char *); 56*26947304SEvan Yan static void parse_flags(int, char **, int *, const char *); 57*26947304SEvan Yan static void parse_target(int, char **, char **, char **, const char *); 58*26947304SEvan Yan static void parse_options(int, char **, char **, const char *); 59*26947304SEvan Yan static void bad_option(int, int, const char *); 60*26947304SEvan Yan static void usage(const char *); 61*26947304SEvan Yan static int list_cb(hp_node_t, void *); 62*26947304SEvan Yan static int list_long_cb(hp_node_t, void *); 63*26947304SEvan Yan static int error_cb(hp_node_t, void *); 64*26947304SEvan Yan static void print_options(const char *); 65*26947304SEvan Yan static void print_error(int); 66*26947304SEvan Yan static int state_atoi(char *); 67*26947304SEvan Yan static char *state_itoa(int); 68*26947304SEvan Yan static short valid_target(int); 69*26947304SEvan Yan 70*26947304SEvan Yan /* 71*26947304SEvan Yan * Define a conversion table for hotplug states. 72*26947304SEvan Yan */ 73*26947304SEvan Yan typedef struct { 74*26947304SEvan Yan int state; 75*26947304SEvan Yan char *state_str; 76*26947304SEvan Yan short valid_target; 77*26947304SEvan Yan } hpstate_t; 78*26947304SEvan Yan 79*26947304SEvan Yan static hpstate_t hpstates[] = { 80*26947304SEvan Yan { DDI_HP_CN_STATE_EMPTY, "EMPTY", 0 }, 81*26947304SEvan Yan { DDI_HP_CN_STATE_PRESENT, "PRESENT", 1 }, 82*26947304SEvan Yan { DDI_HP_CN_STATE_POWERED, "POWERED", 1 }, 83*26947304SEvan Yan { DDI_HP_CN_STATE_ENABLED, "ENABLED", 1 }, 84*26947304SEvan Yan { DDI_HP_CN_STATE_PORT_EMPTY, "PORT-EMPTY", 0 }, 85*26947304SEvan Yan { DDI_HP_CN_STATE_PORT_PRESENT, "PORT-PRESENT", 1 }, 86*26947304SEvan Yan { DDI_HP_CN_STATE_OFFLINE, "OFFLINE", 1 }, 87*26947304SEvan Yan { DDI_HP_CN_STATE_ATTACHED, "ATTACHED", 0 }, 88*26947304SEvan Yan { DDI_HP_CN_STATE_MAINTENANCE, "MAINTENANCE", 0 }, 89*26947304SEvan Yan { DDI_HP_CN_STATE_ONLINE, "ONLINE", 1 }, 90*26947304SEvan Yan { 0, 0, 0 } 91*26947304SEvan Yan }; 92*26947304SEvan Yan 93*26947304SEvan Yan /* 94*26947304SEvan Yan * Define tables of supported subcommands. 95*26947304SEvan Yan */ 96*26947304SEvan Yan typedef struct { 97*26947304SEvan Yan char *usage_str; 98*26947304SEvan Yan char *cmd_str; 99*26947304SEvan Yan int (*func)(int argc, char *argv[], const char *usage_str); 100*26947304SEvan Yan } subcmd_t; 101*26947304SEvan Yan 102*26947304SEvan Yan static subcmd_t subcmds[] = { 103*26947304SEvan Yan { "list [-l] [-v] [<path> [<connection>]]", "list", cmd_list }, 104*26947304SEvan Yan { "online <path> <port>", "online", cmd_online }, 105*26947304SEvan Yan { "offline [-f] [-q] <path> <port>", "offline", cmd_offline }, 106*26947304SEvan Yan { "enable <path> <connector>", "enable", cmd_enable }, 107*26947304SEvan Yan { "disable [-f] [-q] <path> <connector>", "disable", cmd_disable }, 108*26947304SEvan Yan { "poweron <path> <connector>", "poweron", cmd_poweron }, 109*26947304SEvan Yan { "poweroff [-f] [-q] <path> <connector>", "poweroff", cmd_poweroff }, 110*26947304SEvan Yan { "get -o <options> <path> <connector>", "get", cmd_getpriv }, 111*26947304SEvan Yan { "set -o <options> <path> <connector>", "set", cmd_setpriv } 112*26947304SEvan Yan }; 113*26947304SEvan Yan 114*26947304SEvan Yan static subcmd_t hidden_subcmds[] = { 115*26947304SEvan Yan { "changestate [-f] [-q] -s <state> <path> <connection>", 116*26947304SEvan Yan "changestate", cmd_changestate } 117*26947304SEvan Yan }; 118*26947304SEvan Yan 119*26947304SEvan Yan /* 120*26947304SEvan Yan * Define tables of command line options. 121*26947304SEvan Yan */ 122*26947304SEvan Yan static const struct option common_opts[] = { 123*26947304SEvan Yan { "help", no_argument, 0, '?' }, 124*26947304SEvan Yan { "version", no_argument, 0, 'V' }, 125*26947304SEvan Yan { 0, 0, 0, 0 } 126*26947304SEvan Yan }; 127*26947304SEvan Yan 128*26947304SEvan Yan static const struct option list_opts[] = { 129*26947304SEvan Yan { "list-path", no_argument, 0, 'l' }, 130*26947304SEvan Yan { "verbose", no_argument, 0, 'v' }, 131*26947304SEvan Yan { 0, 0, 0, 0 } 132*26947304SEvan Yan }; 133*26947304SEvan Yan 134*26947304SEvan Yan static const struct option flag_opts[] = { 135*26947304SEvan Yan { "force", no_argument, 0, 'f' }, 136*26947304SEvan Yan { "query", no_argument, 0, 'q' }, 137*26947304SEvan Yan { 0, 0, 0, 0 } 138*26947304SEvan Yan }; 139*26947304SEvan Yan 140*26947304SEvan Yan static const struct option private_opts[] = { 141*26947304SEvan Yan { "options", required_argument, 0, 'o' }, 142*26947304SEvan Yan { 0, 0, 0, 0 } 143*26947304SEvan Yan }; 144*26947304SEvan Yan 145*26947304SEvan Yan static const struct option changestate_opts[] = { 146*26947304SEvan Yan { "force", no_argument, 0, 'f' }, 147*26947304SEvan Yan { "query", no_argument, 0, 'q' }, 148*26947304SEvan Yan { "state", required_argument, 0, 's' }, 149*26947304SEvan Yan { 0, 0, 0, 0 } 150*26947304SEvan Yan }; 151*26947304SEvan Yan 152*26947304SEvan Yan /* 153*26947304SEvan Yan * Define exit codes. 154*26947304SEvan Yan */ 155*26947304SEvan Yan #define EXIT_OK 0 156*26947304SEvan Yan #define EXIT_EINVAL 1 /* invalid arguments */ 157*26947304SEvan Yan #define EXIT_ENOENT 2 /* path or connection doesn't exist */ 158*26947304SEvan Yan #define EXIT_FAILED 3 /* operation failed */ 159*26947304SEvan Yan #define EXIT_UNAVAIL 4 /* service not available */ 160*26947304SEvan Yan 161*26947304SEvan Yan /* 162*26947304SEvan Yan * Global variables. 163*26947304SEvan Yan */ 164*26947304SEvan Yan static char *prog; 165*26947304SEvan Yan static char version[] = "1.0"; 166*26947304SEvan Yan extern int errno; 167*26947304SEvan Yan 168*26947304SEvan Yan /* 169*26947304SEvan Yan * main() 170*26947304SEvan Yan * 171*26947304SEvan Yan * The main routine determines which subcommand is used, 172*26947304SEvan Yan * and dispatches control to the corresponding function. 173*26947304SEvan Yan */ 174*26947304SEvan Yan int 175*26947304SEvan Yan main(int argc, char *argv[]) 176*26947304SEvan Yan { 177*26947304SEvan Yan int i, rv; 178*26947304SEvan Yan 179*26947304SEvan Yan (void) setlocale(LC_ALL, ""); 180*26947304SEvan Yan (void) textdomain(TEXT_DOMAIN); 181*26947304SEvan Yan 182*26947304SEvan Yan if ((prog = strrchr(argv[0], '/')) == NULL) 183*26947304SEvan Yan prog = argv[0]; 184*26947304SEvan Yan else 185*26947304SEvan Yan prog++; 186*26947304SEvan Yan 187*26947304SEvan Yan if (argc < 2) { 188*26947304SEvan Yan usage(NULL); 189*26947304SEvan Yan return (EXIT_EINVAL); 190*26947304SEvan Yan } 191*26947304SEvan Yan 192*26947304SEvan Yan parse_common(argc, argv, NULL); 193*26947304SEvan Yan 194*26947304SEvan Yan /* Check the list of defined subcommands. */ 195*26947304SEvan Yan for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++) { 196*26947304SEvan Yan if (strcmp(argv[1], subcmds[i].cmd_str) == 0) { 197*26947304SEvan Yan rv = subcmds[i].func(argc - 1, &argv[1], 198*26947304SEvan Yan subcmds[i].usage_str); 199*26947304SEvan Yan goto finished; 200*26947304SEvan Yan } 201*26947304SEvan Yan } 202*26947304SEvan Yan 203*26947304SEvan Yan /* Check the list of hidden subcommands. */ 204*26947304SEvan Yan for (i = 0; i < (sizeof (hidden_subcmds) / sizeof (subcmd_t)); i++) { 205*26947304SEvan Yan if (strcmp(argv[1], hidden_subcmds[i].cmd_str) == 0) { 206*26947304SEvan Yan rv = hidden_subcmds[i].func(argc - 1, &argv[1], 207*26947304SEvan Yan hidden_subcmds[i].usage_str); 208*26947304SEvan Yan goto finished; 209*26947304SEvan Yan } 210*26947304SEvan Yan } 211*26947304SEvan Yan 212*26947304SEvan Yan /* No matching subcommand found. */ 213*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: %s: unknown subcommand '%s'\n"), 214*26947304SEvan Yan prog, argv[1]); 215*26947304SEvan Yan usage(NULL); 216*26947304SEvan Yan exit(EXIT_EINVAL); 217*26947304SEvan Yan 218*26947304SEvan Yan finished: 219*26947304SEvan Yan /* Determine exit code */ 220*26947304SEvan Yan switch (rv) { 221*26947304SEvan Yan case 0: 222*26947304SEvan Yan break; 223*26947304SEvan Yan case EINVAL: 224*26947304SEvan Yan return (EXIT_EINVAL); 225*26947304SEvan Yan case ENXIO: 226*26947304SEvan Yan case ENOENT: 227*26947304SEvan Yan return (EXIT_ENOENT); 228*26947304SEvan Yan case EBADF: 229*26947304SEvan Yan return (EXIT_UNAVAIL); 230*26947304SEvan Yan default: 231*26947304SEvan Yan return (EXIT_FAILED); 232*26947304SEvan Yan } 233*26947304SEvan Yan 234*26947304SEvan Yan return (EXIT_OK); 235*26947304SEvan Yan } 236*26947304SEvan Yan 237*26947304SEvan Yan /* 238*26947304SEvan Yan * cmd_list() 239*26947304SEvan Yan * 240*26947304SEvan Yan * Subcommand to list hotplug information. 241*26947304SEvan Yan */ 242*26947304SEvan Yan static int 243*26947304SEvan Yan cmd_list(int argc, char *argv[], const char *usage_str) 244*26947304SEvan Yan { 245*26947304SEvan Yan hp_node_t root; 246*26947304SEvan Yan char *path = NULL; 247*26947304SEvan Yan char *connection = NULL; 248*26947304SEvan Yan boolean_t long_flag = B_FALSE; 249*26947304SEvan Yan int flags = 0; 250*26947304SEvan Yan int opt; 251*26947304SEvan Yan 252*26947304SEvan Yan /* Parse command line options */ 253*26947304SEvan Yan parse_common(argc, argv, usage_str); 254*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "lv", list_opts, NULL)) != -1) { 255*26947304SEvan Yan switch (opt) { 256*26947304SEvan Yan case 'l': 257*26947304SEvan Yan long_flag = B_TRUE; 258*26947304SEvan Yan break; 259*26947304SEvan Yan case 'v': 260*26947304SEvan Yan flags |= HPINFOUSAGE; 261*26947304SEvan Yan break; 262*26947304SEvan Yan default: 263*26947304SEvan Yan bad_option(opt, optopt, usage_str); 264*26947304SEvan Yan break; 265*26947304SEvan Yan } 266*26947304SEvan Yan } 267*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 268*26947304SEvan Yan 269*26947304SEvan Yan /* Default path is "/" */ 270*26947304SEvan Yan if (path == NULL) 271*26947304SEvan Yan path = "/"; 272*26947304SEvan Yan 273*26947304SEvan Yan /* Get hotplug information snapshot */ 274*26947304SEvan Yan if ((root = hp_init(path, connection, flags)) == NULL) { 275*26947304SEvan Yan print_error(errno); 276*26947304SEvan Yan return (errno); 277*26947304SEvan Yan } 278*26947304SEvan Yan 279*26947304SEvan Yan /* Display hotplug information */ 280*26947304SEvan Yan (void) hp_traverse(root, NULL, long_flag ? list_long_cb : list_cb); 281*26947304SEvan Yan 282*26947304SEvan Yan /* Discard hotplug information snapshot */ 283*26947304SEvan Yan hp_fini(root); 284*26947304SEvan Yan 285*26947304SEvan Yan return (0); 286*26947304SEvan Yan } 287*26947304SEvan Yan 288*26947304SEvan Yan /* 289*26947304SEvan Yan * cmd_online() 290*26947304SEvan Yan * 291*26947304SEvan Yan * Subcommand to online a hotplug port. 292*26947304SEvan Yan */ 293*26947304SEvan Yan static int 294*26947304SEvan Yan cmd_online(int argc, char *argv[], const char *usage_str) 295*26947304SEvan Yan { 296*26947304SEvan Yan hp_node_t root; 297*26947304SEvan Yan hp_node_t results = NULL; 298*26947304SEvan Yan char *path = NULL; 299*26947304SEvan Yan char *connection = NULL; 300*26947304SEvan Yan int rv; 301*26947304SEvan Yan 302*26947304SEvan Yan /* Parse command line options */ 303*26947304SEvan Yan parse_common(argc, argv, usage_str); 304*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 305*26947304SEvan Yan 306*26947304SEvan Yan /* Path and connection are required */ 307*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) { 308*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 309*26947304SEvan Yan usage(usage_str); 310*26947304SEvan Yan return (EINVAL); 311*26947304SEvan Yan } 312*26947304SEvan Yan 313*26947304SEvan Yan /* Get hotplug information snapshot */ 314*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 315*26947304SEvan Yan print_error(errno); 316*26947304SEvan Yan return (errno); 317*26947304SEvan Yan } 318*26947304SEvan Yan 319*26947304SEvan Yan /* Verify target is a port */ 320*26947304SEvan Yan if (hp_type(root) != HP_NODE_PORT) { 321*26947304SEvan Yan (void) fprintf(stderr, 322*26947304SEvan Yan gettext("ERROR: invalid target (must be a port).\n")); 323*26947304SEvan Yan hp_fini(root); 324*26947304SEvan Yan return (EINVAL); 325*26947304SEvan Yan } 326*26947304SEvan Yan 327*26947304SEvan Yan /* Do state change */ 328*26947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ONLINE, &results); 329*26947304SEvan Yan 330*26947304SEvan Yan /* Display results */ 331*26947304SEvan Yan if (rv == EIO) { 332*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: failed to attach device " 333*26947304SEvan Yan "drivers or other internal errors.\n")); 334*26947304SEvan Yan } else if (rv != 0) { 335*26947304SEvan Yan print_error(rv); 336*26947304SEvan Yan } 337*26947304SEvan Yan if (results != NULL) { 338*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 339*26947304SEvan Yan hp_fini(results); 340*26947304SEvan Yan } 341*26947304SEvan Yan 342*26947304SEvan Yan /* Discard hotplug information snapshot */ 343*26947304SEvan Yan hp_fini(root); 344*26947304SEvan Yan 345*26947304SEvan Yan return (rv); 346*26947304SEvan Yan } 347*26947304SEvan Yan 348*26947304SEvan Yan /* 349*26947304SEvan Yan * cmd_offline() 350*26947304SEvan Yan * 351*26947304SEvan Yan * Subcommand to offline a hotplug port. 352*26947304SEvan Yan */ 353*26947304SEvan Yan static int 354*26947304SEvan Yan cmd_offline(int argc, char *argv[], const char *usage_str) 355*26947304SEvan Yan { 356*26947304SEvan Yan hp_node_t root; 357*26947304SEvan Yan hp_node_t results = NULL; 358*26947304SEvan Yan char *path = NULL; 359*26947304SEvan Yan char *connection = NULL; 360*26947304SEvan Yan int flags = 0; 361*26947304SEvan Yan int rv; 362*26947304SEvan Yan 363*26947304SEvan Yan /* Parse command line options */ 364*26947304SEvan Yan parse_common(argc, argv, usage_str); 365*26947304SEvan Yan parse_flags(argc, argv, &flags, usage_str); 366*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 367*26947304SEvan Yan 368*26947304SEvan Yan /* Path and connection are required */ 369*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) { 370*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 371*26947304SEvan Yan usage(usage_str); 372*26947304SEvan Yan return (EINVAL); 373*26947304SEvan Yan } 374*26947304SEvan Yan 375*26947304SEvan Yan /* Get hotplug information snapshot */ 376*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 377*26947304SEvan Yan print_error(errno); 378*26947304SEvan Yan return (errno); 379*26947304SEvan Yan } 380*26947304SEvan Yan 381*26947304SEvan Yan /* Verify target is a port */ 382*26947304SEvan Yan if (hp_type(root) != HP_NODE_PORT) { 383*26947304SEvan Yan (void) fprintf(stderr, 384*26947304SEvan Yan gettext("ERROR: invalid target (must be a port).\n")); 385*26947304SEvan Yan hp_fini(root); 386*26947304SEvan Yan return (EINVAL); 387*26947304SEvan Yan } 388*26947304SEvan Yan 389*26947304SEvan Yan /* Do state change */ 390*26947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_OFFLINE, &results); 391*26947304SEvan Yan 392*26947304SEvan Yan /* Display results */ 393*26947304SEvan Yan print_error(rv); 394*26947304SEvan Yan if (results != NULL) { 395*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 396*26947304SEvan Yan hp_fini(results); 397*26947304SEvan Yan } 398*26947304SEvan Yan 399*26947304SEvan Yan /* Discard hotplug information snapshot */ 400*26947304SEvan Yan hp_fini(root); 401*26947304SEvan Yan 402*26947304SEvan Yan return (rv); 403*26947304SEvan Yan } 404*26947304SEvan Yan 405*26947304SEvan Yan /* 406*26947304SEvan Yan * cmd_enable() 407*26947304SEvan Yan * 408*26947304SEvan Yan * Subcommand to enable a hotplug connector. 409*26947304SEvan Yan */ 410*26947304SEvan Yan static int 411*26947304SEvan Yan cmd_enable(int argc, char *argv[], const char *usage_str) 412*26947304SEvan Yan { 413*26947304SEvan Yan hp_node_t root; 414*26947304SEvan Yan hp_node_t results = NULL; 415*26947304SEvan Yan char *path = NULL; 416*26947304SEvan Yan char *connection = NULL; 417*26947304SEvan Yan int rv; 418*26947304SEvan Yan 419*26947304SEvan Yan /* Parse command line options */ 420*26947304SEvan Yan parse_common(argc, argv, usage_str); 421*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 422*26947304SEvan Yan 423*26947304SEvan Yan /* Path and connection are required */ 424*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) { 425*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 426*26947304SEvan Yan usage(usage_str); 427*26947304SEvan Yan return (EINVAL); 428*26947304SEvan Yan } 429*26947304SEvan Yan 430*26947304SEvan Yan /* Get hotplug information snapshot */ 431*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 432*26947304SEvan Yan print_error(errno); 433*26947304SEvan Yan return (errno); 434*26947304SEvan Yan } 435*26947304SEvan Yan 436*26947304SEvan Yan /* Verify target is a connector */ 437*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) { 438*26947304SEvan Yan (void) fprintf(stderr, 439*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n")); 440*26947304SEvan Yan hp_fini(root); 441*26947304SEvan Yan return (EINVAL); 442*26947304SEvan Yan } 443*26947304SEvan Yan 444*26947304SEvan Yan /* Do state change */ 445*26947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ENABLED, &results); 446*26947304SEvan Yan 447*26947304SEvan Yan /* Display results */ 448*26947304SEvan Yan print_error(rv); 449*26947304SEvan Yan if (results != NULL) { 450*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 451*26947304SEvan Yan hp_fini(results); 452*26947304SEvan Yan } 453*26947304SEvan Yan 454*26947304SEvan Yan /* Discard hotplug information snapshot */ 455*26947304SEvan Yan hp_fini(root); 456*26947304SEvan Yan 457*26947304SEvan Yan return (rv); 458*26947304SEvan Yan } 459*26947304SEvan Yan 460*26947304SEvan Yan /* 461*26947304SEvan Yan * cmd_disable() 462*26947304SEvan Yan * 463*26947304SEvan Yan * Subcommand to disable a hotplug connector. 464*26947304SEvan Yan */ 465*26947304SEvan Yan static int 466*26947304SEvan Yan cmd_disable(int argc, char *argv[], const char *usage_str) 467*26947304SEvan Yan { 468*26947304SEvan Yan hp_node_t root; 469*26947304SEvan Yan hp_node_t results = NULL; 470*26947304SEvan Yan char *path = NULL; 471*26947304SEvan Yan char *connection = NULL; 472*26947304SEvan Yan int flags = 0; 473*26947304SEvan Yan int rv; 474*26947304SEvan Yan 475*26947304SEvan Yan /* Parse command line options */ 476*26947304SEvan Yan parse_common(argc, argv, usage_str); 477*26947304SEvan Yan parse_flags(argc, argv, &flags, usage_str); 478*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 479*26947304SEvan Yan 480*26947304SEvan Yan /* Path and connection are required */ 481*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) { 482*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 483*26947304SEvan Yan usage(usage_str); 484*26947304SEvan Yan return (EINVAL); 485*26947304SEvan Yan } 486*26947304SEvan Yan 487*26947304SEvan Yan /* Get hotplug information snapshot */ 488*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 489*26947304SEvan Yan print_error(errno); 490*26947304SEvan Yan return (errno); 491*26947304SEvan Yan } 492*26947304SEvan Yan 493*26947304SEvan Yan /* Verify target is a connector */ 494*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) { 495*26947304SEvan Yan (void) fprintf(stderr, 496*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n")); 497*26947304SEvan Yan hp_fini(root); 498*26947304SEvan Yan return (EINVAL); 499*26947304SEvan Yan } 500*26947304SEvan Yan 501*26947304SEvan Yan /* 502*26947304SEvan Yan * Do nothing unless the connector is in the ENABLED state. 503*26947304SEvan Yan * Otherwise this subcommand becomes an alias for 'poweron.' 504*26947304SEvan Yan */ 505*26947304SEvan Yan if (hp_state(root) != DDI_HP_CN_STATE_ENABLED) { 506*26947304SEvan Yan hp_fini(root); 507*26947304SEvan Yan return (0); 508*26947304SEvan Yan } 509*26947304SEvan Yan 510*26947304SEvan Yan /* Do state change */ 511*26947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_POWERED, &results); 512*26947304SEvan Yan 513*26947304SEvan Yan /* Display results */ 514*26947304SEvan Yan print_error(rv); 515*26947304SEvan Yan if (results != NULL) { 516*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 517*26947304SEvan Yan hp_fini(results); 518*26947304SEvan Yan } 519*26947304SEvan Yan 520*26947304SEvan Yan /* Discard hotplug information snapshot */ 521*26947304SEvan Yan hp_fini(root); 522*26947304SEvan Yan 523*26947304SEvan Yan return (rv); 524*26947304SEvan Yan } 525*26947304SEvan Yan 526*26947304SEvan Yan /* 527*26947304SEvan Yan * cmd_poweron() 528*26947304SEvan Yan * 529*26947304SEvan Yan * Subcommand to power on a hotplug connector. 530*26947304SEvan Yan */ 531*26947304SEvan Yan static int 532*26947304SEvan Yan cmd_poweron(int argc, char *argv[], const char *usage_str) 533*26947304SEvan Yan { 534*26947304SEvan Yan hp_node_t root; 535*26947304SEvan Yan hp_node_t results = NULL; 536*26947304SEvan Yan char *path = NULL; 537*26947304SEvan Yan char *connection = NULL; 538*26947304SEvan Yan int rv; 539*26947304SEvan Yan 540*26947304SEvan Yan /* Parse command line options */ 541*26947304SEvan Yan parse_common(argc, argv, usage_str); 542*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 543*26947304SEvan Yan 544*26947304SEvan Yan /* Path and connection are required */ 545*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) { 546*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 547*26947304SEvan Yan usage(usage_str); 548*26947304SEvan Yan return (EINVAL); 549*26947304SEvan Yan } 550*26947304SEvan Yan 551*26947304SEvan Yan /* Get hotplug information snapshot */ 552*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 553*26947304SEvan Yan print_error(errno); 554*26947304SEvan Yan return (errno); 555*26947304SEvan Yan } 556*26947304SEvan Yan 557*26947304SEvan Yan /* Verify target is a connector */ 558*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) { 559*26947304SEvan Yan (void) fprintf(stderr, 560*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n")); 561*26947304SEvan Yan hp_fini(root); 562*26947304SEvan Yan return (EINVAL); 563*26947304SEvan Yan } 564*26947304SEvan Yan 565*26947304SEvan Yan /* 566*26947304SEvan Yan * Do nothing if the connector is already powered. 567*26947304SEvan Yan * Otherwise this subcommand becomes an alias for 'disable.' 568*26947304SEvan Yan */ 569*26947304SEvan Yan if (hp_state(root) >= DDI_HP_CN_STATE_POWERED) { 570*26947304SEvan Yan hp_fini(root); 571*26947304SEvan Yan return (0); 572*26947304SEvan Yan } 573*26947304SEvan Yan 574*26947304SEvan Yan /* Do state change */ 575*26947304SEvan Yan rv = hp_set_state(root, 0, DDI_HP_CN_STATE_POWERED, &results); 576*26947304SEvan Yan 577*26947304SEvan Yan /* Display results */ 578*26947304SEvan Yan print_error(rv); 579*26947304SEvan Yan if (results != NULL) { 580*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 581*26947304SEvan Yan hp_fini(results); 582*26947304SEvan Yan } 583*26947304SEvan Yan 584*26947304SEvan Yan /* Discard hotplug information snapshot */ 585*26947304SEvan Yan hp_fini(root); 586*26947304SEvan Yan 587*26947304SEvan Yan return (rv); 588*26947304SEvan Yan } 589*26947304SEvan Yan 590*26947304SEvan Yan /* 591*26947304SEvan Yan * cmd_poweroff() 592*26947304SEvan Yan * 593*26947304SEvan Yan * Subcommand to power off a hotplug connector. 594*26947304SEvan Yan */ 595*26947304SEvan Yan static int 596*26947304SEvan Yan cmd_poweroff(int argc, char *argv[], const char *usage_str) 597*26947304SEvan Yan { 598*26947304SEvan Yan hp_node_t root; 599*26947304SEvan Yan hp_node_t results = NULL; 600*26947304SEvan Yan char *path = NULL; 601*26947304SEvan Yan char *connection = NULL; 602*26947304SEvan Yan int flags = 0; 603*26947304SEvan Yan int rv; 604*26947304SEvan Yan 605*26947304SEvan Yan /* Parse command line options */ 606*26947304SEvan Yan parse_common(argc, argv, usage_str); 607*26947304SEvan Yan parse_flags(argc, argv, &flags, usage_str); 608*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 609*26947304SEvan Yan 610*26947304SEvan Yan /* Path and connection are required */ 611*26947304SEvan Yan if ((path == NULL) || (connection == NULL)) { 612*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 613*26947304SEvan Yan usage(usage_str); 614*26947304SEvan Yan return (EINVAL); 615*26947304SEvan Yan } 616*26947304SEvan Yan 617*26947304SEvan Yan /* Get hotplug information snapshot */ 618*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 619*26947304SEvan Yan print_error(errno); 620*26947304SEvan Yan return (errno); 621*26947304SEvan Yan } 622*26947304SEvan Yan 623*26947304SEvan Yan /* Verify target is a connector */ 624*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) { 625*26947304SEvan Yan (void) fprintf(stderr, 626*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n")); 627*26947304SEvan Yan hp_fini(root); 628*26947304SEvan Yan return (EINVAL); 629*26947304SEvan Yan } 630*26947304SEvan Yan 631*26947304SEvan Yan /* Do state change */ 632*26947304SEvan Yan rv = hp_set_state(root, flags, DDI_HP_CN_STATE_PRESENT, &results); 633*26947304SEvan Yan 634*26947304SEvan Yan /* Display results */ 635*26947304SEvan Yan print_error(rv); 636*26947304SEvan Yan if (results != NULL) { 637*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 638*26947304SEvan Yan hp_fini(results); 639*26947304SEvan Yan } 640*26947304SEvan Yan 641*26947304SEvan Yan /* Discard hotplug information snapshot */ 642*26947304SEvan Yan hp_fini(root); 643*26947304SEvan Yan 644*26947304SEvan Yan return (rv); 645*26947304SEvan Yan } 646*26947304SEvan Yan 647*26947304SEvan Yan /* 648*26947304SEvan Yan * cmd_getpriv() 649*26947304SEvan Yan * 650*26947304SEvan Yan * Subcommand to get and display bus private options. 651*26947304SEvan Yan */ 652*26947304SEvan Yan static int 653*26947304SEvan Yan cmd_getpriv(int argc, char *argv[], const char *usage_str) 654*26947304SEvan Yan { 655*26947304SEvan Yan hp_node_t root; 656*26947304SEvan Yan char *path = NULL; 657*26947304SEvan Yan char *connection = NULL; 658*26947304SEvan Yan char *options = NULL; 659*26947304SEvan Yan char *results = NULL; 660*26947304SEvan Yan int rv; 661*26947304SEvan Yan 662*26947304SEvan Yan /* Parse command line options */ 663*26947304SEvan Yan parse_common(argc, argv, usage_str); 664*26947304SEvan Yan parse_options(argc, argv, &options, usage_str); 665*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 666*26947304SEvan Yan 667*26947304SEvan Yan /* Options, path, and connection are all required */ 668*26947304SEvan Yan if ((options == NULL) || (path == NULL) || (connection == NULL)) { 669*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 670*26947304SEvan Yan usage(usage_str); 671*26947304SEvan Yan return (EINVAL); 672*26947304SEvan Yan } 673*26947304SEvan Yan 674*26947304SEvan Yan /* Get hotplug information snapshot */ 675*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 676*26947304SEvan Yan print_error(errno); 677*26947304SEvan Yan return (errno); 678*26947304SEvan Yan } 679*26947304SEvan Yan 680*26947304SEvan Yan /* Verify target is a connector */ 681*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) { 682*26947304SEvan Yan (void) fprintf(stderr, 683*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n")); 684*26947304SEvan Yan hp_fini(root); 685*26947304SEvan Yan return (EINVAL); 686*26947304SEvan Yan } 687*26947304SEvan Yan 688*26947304SEvan Yan /* Do the operation */ 689*26947304SEvan Yan rv = hp_get_private(root, options, &results); 690*26947304SEvan Yan 691*26947304SEvan Yan /* Display results */ 692*26947304SEvan Yan if (rv == ENOTSUP) { 693*26947304SEvan Yan (void) fprintf(stderr, 694*26947304SEvan Yan gettext("ERROR: unsupported property name or value.\n")); 695*26947304SEvan Yan (void) fprintf(stderr, 696*26947304SEvan Yan gettext("(Properties may depend upon connector state.)\n")); 697*26947304SEvan Yan } else if (rv != 0) { 698*26947304SEvan Yan print_error(rv); 699*26947304SEvan Yan } 700*26947304SEvan Yan if (results != NULL) { 701*26947304SEvan Yan print_options(results); 702*26947304SEvan Yan free(results); 703*26947304SEvan Yan } 704*26947304SEvan Yan 705*26947304SEvan Yan /* Discard hotplug information snapshot */ 706*26947304SEvan Yan hp_fini(root); 707*26947304SEvan Yan 708*26947304SEvan Yan return (rv); 709*26947304SEvan Yan } 710*26947304SEvan Yan 711*26947304SEvan Yan /* 712*26947304SEvan Yan * cmd_setpriv() 713*26947304SEvan Yan * 714*26947304SEvan Yan * Subcommand to set bus private options. 715*26947304SEvan Yan */ 716*26947304SEvan Yan static int 717*26947304SEvan Yan cmd_setpriv(int argc, char *argv[], const char *usage_str) 718*26947304SEvan Yan { 719*26947304SEvan Yan hp_node_t root; 720*26947304SEvan Yan char *path = NULL; 721*26947304SEvan Yan char *connection = NULL; 722*26947304SEvan Yan char *options = NULL; 723*26947304SEvan Yan char *results = NULL; 724*26947304SEvan Yan int rv; 725*26947304SEvan Yan 726*26947304SEvan Yan /* Parse command line options */ 727*26947304SEvan Yan parse_common(argc, argv, usage_str); 728*26947304SEvan Yan parse_options(argc, argv, &options, usage_str); 729*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 730*26947304SEvan Yan 731*26947304SEvan Yan /* Options, path, and connection are all required */ 732*26947304SEvan Yan if ((options == NULL) || (path == NULL) || (connection == NULL)) { 733*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 734*26947304SEvan Yan usage(usage_str); 735*26947304SEvan Yan return (EINVAL); 736*26947304SEvan Yan } 737*26947304SEvan Yan 738*26947304SEvan Yan /* Get hotplug information snapshot */ 739*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 740*26947304SEvan Yan print_error(errno); 741*26947304SEvan Yan return (errno); 742*26947304SEvan Yan } 743*26947304SEvan Yan 744*26947304SEvan Yan /* Verify target is a connector */ 745*26947304SEvan Yan if (hp_type(root) != HP_NODE_CONNECTOR) { 746*26947304SEvan Yan (void) fprintf(stderr, 747*26947304SEvan Yan gettext("ERROR: invalid target (must be a connector).\n")); 748*26947304SEvan Yan hp_fini(root); 749*26947304SEvan Yan return (EINVAL); 750*26947304SEvan Yan } 751*26947304SEvan Yan 752*26947304SEvan Yan /* Do the operation */ 753*26947304SEvan Yan rv = hp_set_private(root, options, &results); 754*26947304SEvan Yan 755*26947304SEvan Yan /* Display results */ 756*26947304SEvan Yan if (rv == ENOTSUP) { 757*26947304SEvan Yan (void) fprintf(stderr, 758*26947304SEvan Yan gettext("ERROR: unsupported property name or value.\n")); 759*26947304SEvan Yan (void) fprintf(stderr, 760*26947304SEvan Yan gettext("(Properties may depend upon connector state.)\n")); 761*26947304SEvan Yan } else if (rv != 0) { 762*26947304SEvan Yan print_error(rv); 763*26947304SEvan Yan } 764*26947304SEvan Yan if (results != NULL) { 765*26947304SEvan Yan print_options(results); 766*26947304SEvan Yan free(results); 767*26947304SEvan Yan } 768*26947304SEvan Yan 769*26947304SEvan Yan /* Discard hotplug information snapshot */ 770*26947304SEvan Yan hp_fini(root); 771*26947304SEvan Yan 772*26947304SEvan Yan return (rv); 773*26947304SEvan Yan } 774*26947304SEvan Yan 775*26947304SEvan Yan /* 776*26947304SEvan Yan * cmd_changestate() 777*26947304SEvan Yan * 778*26947304SEvan Yan * Subcommand to initiate a state change operation. This is 779*26947304SEvan Yan * a hidden subcommand to directly set a connector or port to 780*26947304SEvan Yan * a specific target state. 781*26947304SEvan Yan */ 782*26947304SEvan Yan static int 783*26947304SEvan Yan cmd_changestate(int argc, char *argv[], const char *usage_str) 784*26947304SEvan Yan { 785*26947304SEvan Yan hp_node_t root; 786*26947304SEvan Yan hp_node_t results = NULL; 787*26947304SEvan Yan char *path = NULL; 788*26947304SEvan Yan char *connection = NULL; 789*26947304SEvan Yan int state = -1; 790*26947304SEvan Yan int flags = 0; 791*26947304SEvan Yan int opt, rv; 792*26947304SEvan Yan 793*26947304SEvan Yan /* Parse command line options */ 794*26947304SEvan Yan parse_common(argc, argv, usage_str); 795*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "fqs:", changestate_opts, 796*26947304SEvan Yan NULL)) != -1) { 797*26947304SEvan Yan switch (opt) { 798*26947304SEvan Yan case 'f': 799*26947304SEvan Yan flags |= HPFORCE; 800*26947304SEvan Yan break; 801*26947304SEvan Yan case 'q': 802*26947304SEvan Yan flags |= HPQUERY; 803*26947304SEvan Yan break; 804*26947304SEvan Yan case 's': 805*26947304SEvan Yan if ((state = state_atoi(optarg)) == -1) { 806*26947304SEvan Yan (void) printf("ERROR: invalid target state\n"); 807*26947304SEvan Yan return (EINVAL); 808*26947304SEvan Yan } 809*26947304SEvan Yan break; 810*26947304SEvan Yan default: 811*26947304SEvan Yan bad_option(opt, optopt, usage_str); 812*26947304SEvan Yan break; 813*26947304SEvan Yan } 814*26947304SEvan Yan } 815*26947304SEvan Yan parse_target(argc, argv, &path, &connection, usage_str); 816*26947304SEvan Yan 817*26947304SEvan Yan /* State, path, and connection are all required */ 818*26947304SEvan Yan if ((state == -1) || (path == NULL) || (connection == NULL)) { 819*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too few arguments.\n")); 820*26947304SEvan Yan usage(usage_str); 821*26947304SEvan Yan return (EINVAL); 822*26947304SEvan Yan } 823*26947304SEvan Yan 824*26947304SEvan Yan /* Check that target state is valid */ 825*26947304SEvan Yan if (valid_target(state) == 0) { 826*26947304SEvan Yan (void) fprintf(stderr, 827*26947304SEvan Yan gettext("ERROR: invalid target state\n")); 828*26947304SEvan Yan return (EINVAL); 829*26947304SEvan Yan } 830*26947304SEvan Yan 831*26947304SEvan Yan /* Get hotplug information snapshot */ 832*26947304SEvan Yan if ((root = hp_init(path, connection, 0)) == NULL) { 833*26947304SEvan Yan print_error(errno); 834*26947304SEvan Yan return (errno); 835*26947304SEvan Yan } 836*26947304SEvan Yan 837*26947304SEvan Yan /* Initiate state change operation on root of snapshot */ 838*26947304SEvan Yan rv = hp_set_state(root, flags, state, &results); 839*26947304SEvan Yan 840*26947304SEvan Yan /* Display results */ 841*26947304SEvan Yan print_error(rv); 842*26947304SEvan Yan if (results) { 843*26947304SEvan Yan (void) hp_traverse(results, NULL, error_cb); 844*26947304SEvan Yan hp_fini(results); 845*26947304SEvan Yan } 846*26947304SEvan Yan 847*26947304SEvan Yan /* Discard hotplug information snapshot */ 848*26947304SEvan Yan hp_fini(root); 849*26947304SEvan Yan 850*26947304SEvan Yan return (rv); 851*26947304SEvan Yan } 852*26947304SEvan Yan 853*26947304SEvan Yan /* 854*26947304SEvan Yan * parse_common() 855*26947304SEvan Yan * 856*26947304SEvan Yan * Parse command line options that are common to the 857*26947304SEvan Yan * entire program, and to each of its subcommands. 858*26947304SEvan Yan */ 859*26947304SEvan Yan static void 860*26947304SEvan Yan parse_common(int argc, char *argv[], const char *usage_str) 861*26947304SEvan Yan { 862*26947304SEvan Yan int opt; 863*26947304SEvan Yan extern int opterr; 864*26947304SEvan Yan extern int optind; 865*26947304SEvan Yan 866*26947304SEvan Yan /* Turn off error reporting */ 867*26947304SEvan Yan opterr = 0; 868*26947304SEvan Yan 869*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "?V", common_opts, NULL)) != -1) { 870*26947304SEvan Yan switch (opt) { 871*26947304SEvan Yan case '?': 872*26947304SEvan Yan if (optopt == '?') { 873*26947304SEvan Yan usage(usage_str); 874*26947304SEvan Yan exit(0); 875*26947304SEvan Yan } 876*26947304SEvan Yan break; 877*26947304SEvan Yan case 'V': 878*26947304SEvan Yan (void) printf(gettext("%s: Version %s\n"), 879*26947304SEvan Yan prog, version); 880*26947304SEvan Yan exit(0); 881*26947304SEvan Yan default: 882*26947304SEvan Yan break; 883*26947304SEvan Yan } 884*26947304SEvan Yan } 885*26947304SEvan Yan 886*26947304SEvan Yan /* Reset option index */ 887*26947304SEvan Yan optind = 1; 888*26947304SEvan Yan } 889*26947304SEvan Yan 890*26947304SEvan Yan /* 891*26947304SEvan Yan * parse_flags() 892*26947304SEvan Yan * 893*26947304SEvan Yan * Parse command line flags common to all downward state 894*26947304SEvan Yan * change operations (offline, disable, poweoff). 895*26947304SEvan Yan */ 896*26947304SEvan Yan static void 897*26947304SEvan Yan parse_flags(int argc, char *argv[], int *flagsp, const char *usage_str) 898*26947304SEvan Yan { 899*26947304SEvan Yan int opt; 900*26947304SEvan Yan int flags = 0; 901*26947304SEvan Yan 902*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "fq", flag_opts, NULL)) != -1) { 903*26947304SEvan Yan switch (opt) { 904*26947304SEvan Yan case 'f': 905*26947304SEvan Yan flags |= HPFORCE; 906*26947304SEvan Yan break; 907*26947304SEvan Yan case 'q': 908*26947304SEvan Yan flags |= HPQUERY; 909*26947304SEvan Yan break; 910*26947304SEvan Yan default: 911*26947304SEvan Yan bad_option(opt, optopt, usage_str); 912*26947304SEvan Yan break; 913*26947304SEvan Yan } 914*26947304SEvan Yan } 915*26947304SEvan Yan 916*26947304SEvan Yan *flagsp = flags; 917*26947304SEvan Yan } 918*26947304SEvan Yan 919*26947304SEvan Yan /* 920*26947304SEvan Yan * parse_options() 921*26947304SEvan Yan * 922*26947304SEvan Yan * Parse command line options common to the bus private set and 923*26947304SEvan Yan * get subcommands. 924*26947304SEvan Yan */ 925*26947304SEvan Yan static void 926*26947304SEvan Yan parse_options(int argc, char *argv[], char **optionsp, const char *usage_str) 927*26947304SEvan Yan { 928*26947304SEvan Yan int opt; 929*26947304SEvan Yan 930*26947304SEvan Yan while ((opt = getopt_clip(argc, argv, "o:", private_opts, 931*26947304SEvan Yan NULL)) != -1) { 932*26947304SEvan Yan switch (opt) { 933*26947304SEvan Yan case 'o': 934*26947304SEvan Yan *optionsp = optarg; 935*26947304SEvan Yan break; 936*26947304SEvan Yan default: 937*26947304SEvan Yan bad_option(opt, optopt, usage_str); 938*26947304SEvan Yan break; 939*26947304SEvan Yan } 940*26947304SEvan Yan } 941*26947304SEvan Yan } 942*26947304SEvan Yan 943*26947304SEvan Yan /* 944*26947304SEvan Yan * parse_target() 945*26947304SEvan Yan * 946*26947304SEvan Yan * Parse the target path and connection name from the command line. 947*26947304SEvan Yan */ 948*26947304SEvan Yan static void 949*26947304SEvan Yan parse_target(int argc, char *argv[], char **pathp, char **connectionp, 950*26947304SEvan Yan const char *usage_str) 951*26947304SEvan Yan { 952*26947304SEvan Yan extern int optind; 953*26947304SEvan Yan 954*26947304SEvan Yan if (optind < argc) 955*26947304SEvan Yan *pathp = argv[optind++]; 956*26947304SEvan Yan 957*26947304SEvan Yan if (optind < argc) 958*26947304SEvan Yan *connectionp = argv[optind++]; 959*26947304SEvan Yan 960*26947304SEvan Yan if (optind < argc) { 961*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: too many arguments.\n")); 962*26947304SEvan Yan usage(usage_str); 963*26947304SEvan Yan exit(EINVAL); 964*26947304SEvan Yan } 965*26947304SEvan Yan } 966*26947304SEvan Yan 967*26947304SEvan Yan /* 968*26947304SEvan Yan * bad_option() 969*26947304SEvan Yan * 970*26947304SEvan Yan * Routine to handle bad command line options. 971*26947304SEvan Yan */ 972*26947304SEvan Yan static void 973*26947304SEvan Yan bad_option(int opt, int optopt, const char *usage_str) 974*26947304SEvan Yan { 975*26947304SEvan Yan switch (opt) { 976*26947304SEvan Yan case ':': 977*26947304SEvan Yan (void) fprintf(stderr, 978*26947304SEvan Yan gettext("ERROR: option '%c' requires an argument.\n"), 979*26947304SEvan Yan optopt); 980*26947304SEvan Yan break; 981*26947304SEvan Yan default: 982*26947304SEvan Yan if (optopt == '?') { 983*26947304SEvan Yan usage(usage_str); 984*26947304SEvan Yan exit(EXIT_OK); 985*26947304SEvan Yan } 986*26947304SEvan Yan (void) fprintf(stderr, 987*26947304SEvan Yan gettext("ERROR: unrecognized option '%c'.\n"), optopt); 988*26947304SEvan Yan break; 989*26947304SEvan Yan } 990*26947304SEvan Yan 991*26947304SEvan Yan usage(usage_str); 992*26947304SEvan Yan 993*26947304SEvan Yan exit(EXIT_EINVAL); 994*26947304SEvan Yan } 995*26947304SEvan Yan 996*26947304SEvan Yan /* 997*26947304SEvan Yan * usage() 998*26947304SEvan Yan * 999*26947304SEvan Yan * Display general usage of the command. Including 1000*26947304SEvan Yan * the usage synopsis of each defined subcommand. 1001*26947304SEvan Yan */ 1002*26947304SEvan Yan static void 1003*26947304SEvan Yan usage(const char *usage_str) 1004*26947304SEvan Yan { 1005*26947304SEvan Yan int i; 1006*26947304SEvan Yan 1007*26947304SEvan Yan if (usage_str != NULL) { 1008*26947304SEvan Yan (void) fprintf(stderr, gettext("Usage: %s %s\n\n"), 1009*26947304SEvan Yan prog, usage_str); 1010*26947304SEvan Yan return; 1011*26947304SEvan Yan } 1012*26947304SEvan Yan 1013*26947304SEvan Yan (void) fprintf(stderr, gettext("Usage: %s <subcommand> [<args>]\n\n"), 1014*26947304SEvan Yan prog); 1015*26947304SEvan Yan 1016*26947304SEvan Yan (void) fprintf(stderr, gettext("Subcommands:\n\n")); 1017*26947304SEvan Yan 1018*26947304SEvan Yan for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++) 1019*26947304SEvan Yan (void) fprintf(stderr, " %s\n\n", subcmds[i].usage_str); 1020*26947304SEvan Yan } 1021*26947304SEvan Yan 1022*26947304SEvan Yan /* 1023*26947304SEvan Yan * list_cb() 1024*26947304SEvan Yan * 1025*26947304SEvan Yan * Callback function for hp_traverse(), to display nodes 1026*26947304SEvan Yan * of a hotplug information snapshot. (Short version.) 1027*26947304SEvan Yan */ 1028*26947304SEvan Yan /*ARGSUSED*/ 1029*26947304SEvan Yan static int 1030*26947304SEvan Yan list_cb(hp_node_t node, void *arg) 1031*26947304SEvan Yan { 1032*26947304SEvan Yan hp_node_t parent; 1033*26947304SEvan Yan 1034*26947304SEvan Yan /* Indent */ 1035*26947304SEvan Yan for (parent = hp_parent(node); parent; parent = hp_parent(parent)) 1036*26947304SEvan Yan if (hp_type(parent) == HP_NODE_DEVICE) 1037*26947304SEvan Yan (void) printf(" "); 1038*26947304SEvan Yan 1039*26947304SEvan Yan switch (hp_type(node)) { 1040*26947304SEvan Yan case HP_NODE_DEVICE: 1041*26947304SEvan Yan (void) printf("%s\n", hp_name(node)); 1042*26947304SEvan Yan break; 1043*26947304SEvan Yan 1044*26947304SEvan Yan case HP_NODE_CONNECTOR: 1045*26947304SEvan Yan (void) printf("[%s]", hp_name(node)); 1046*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node))); 1047*26947304SEvan Yan (void) printf("\n"); 1048*26947304SEvan Yan break; 1049*26947304SEvan Yan 1050*26947304SEvan Yan case HP_NODE_PORT: 1051*26947304SEvan Yan (void) printf("<%s>", hp_name(node)); 1052*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node))); 1053*26947304SEvan Yan (void) printf("\n"); 1054*26947304SEvan Yan break; 1055*26947304SEvan Yan 1056*26947304SEvan Yan case HP_NODE_USAGE: 1057*26947304SEvan Yan (void) printf("{ %s }\n", hp_usage(node)); 1058*26947304SEvan Yan break; 1059*26947304SEvan Yan } 1060*26947304SEvan Yan 1061*26947304SEvan Yan return (HP_WALK_CONTINUE); 1062*26947304SEvan Yan } 1063*26947304SEvan Yan 1064*26947304SEvan Yan /* 1065*26947304SEvan Yan * list_long_cb() 1066*26947304SEvan Yan * 1067*26947304SEvan Yan * Callback function for hp_traverse(), to display nodes 1068*26947304SEvan Yan * of a hotplug information snapshot. (Long version.) 1069*26947304SEvan Yan */ 1070*26947304SEvan Yan /*ARGSUSED*/ 1071*26947304SEvan Yan static int 1072*26947304SEvan Yan list_long_cb(hp_node_t node, void *arg) 1073*26947304SEvan Yan { 1074*26947304SEvan Yan char path[MAXPATHLEN]; 1075*26947304SEvan Yan char connection[MAXPATHLEN]; 1076*26947304SEvan Yan 1077*26947304SEvan Yan if (hp_type(node) != HP_NODE_USAGE) { 1078*26947304SEvan Yan if (hp_path(node, path, connection) != 0) 1079*26947304SEvan Yan return (HP_WALK_CONTINUE); 1080*26947304SEvan Yan (void) printf("%s", path); 1081*26947304SEvan Yan } 1082*26947304SEvan Yan 1083*26947304SEvan Yan switch (hp_type(node)) { 1084*26947304SEvan Yan case HP_NODE_CONNECTOR: 1085*26947304SEvan Yan (void) printf(" [%s]", connection); 1086*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node))); 1087*26947304SEvan Yan break; 1088*26947304SEvan Yan 1089*26947304SEvan Yan case HP_NODE_PORT: 1090*26947304SEvan Yan (void) printf(" <%s>", connection); 1091*26947304SEvan Yan (void) printf(" (%s)", state_itoa(hp_state(node))); 1092*26947304SEvan Yan break; 1093*26947304SEvan Yan 1094*26947304SEvan Yan case HP_NODE_USAGE: 1095*26947304SEvan Yan (void) printf(" { %s }", hp_usage(node)); 1096*26947304SEvan Yan break; 1097*26947304SEvan Yan } 1098*26947304SEvan Yan 1099*26947304SEvan Yan (void) printf("\n"); 1100*26947304SEvan Yan 1101*26947304SEvan Yan return (HP_WALK_CONTINUE); 1102*26947304SEvan Yan } 1103*26947304SEvan Yan 1104*26947304SEvan Yan /* 1105*26947304SEvan Yan * error_cb() 1106*26947304SEvan Yan * 1107*26947304SEvan Yan * Callback function for hp_traverse(), to display 1108*26947304SEvan Yan * error results from a state change operation. 1109*26947304SEvan Yan */ 1110*26947304SEvan Yan /*ARGSUSED*/ 1111*26947304SEvan Yan static int 1112*26947304SEvan Yan error_cb(hp_node_t node, void *arg) 1113*26947304SEvan Yan { 1114*26947304SEvan Yan hp_node_t child; 1115*26947304SEvan Yan char *usage_str; 1116*26947304SEvan Yan static char path[MAXPATHLEN]; 1117*26947304SEvan Yan static char connection[MAXPATHLEN]; 1118*26947304SEvan Yan 1119*26947304SEvan Yan if (((child = hp_child(node)) != NULL) && 1120*26947304SEvan Yan (hp_type(child) == HP_NODE_USAGE)) { 1121*26947304SEvan Yan if (hp_path(node, path, connection) == 0) 1122*26947304SEvan Yan (void) printf("%s:\n", path); 1123*26947304SEvan Yan return (HP_WALK_CONTINUE); 1124*26947304SEvan Yan } 1125*26947304SEvan Yan 1126*26947304SEvan Yan if ((hp_type(node) == HP_NODE_USAGE) && 1127*26947304SEvan Yan ((usage_str = hp_usage(node)) != NULL)) 1128*26947304SEvan Yan (void) printf(" { %s }\n", usage_str); 1129*26947304SEvan Yan 1130*26947304SEvan Yan return (HP_WALK_CONTINUE); 1131*26947304SEvan Yan } 1132*26947304SEvan Yan 1133*26947304SEvan Yan /* 1134*26947304SEvan Yan * print_options() 1135*26947304SEvan Yan * 1136*26947304SEvan Yan * Parse and display bus private options. The options are 1137*26947304SEvan Yan * formatted as a string which conforms to the getsubopt(3C) 1138*26947304SEvan Yan * format. This routine only splits the string elements as 1139*26947304SEvan Yan * separated by commas, and displays each portion on its own 1140*26947304SEvan Yan * separate line of output. 1141*26947304SEvan Yan */ 1142*26947304SEvan Yan static void 1143*26947304SEvan Yan print_options(const char *options) 1144*26947304SEvan Yan { 1145*26947304SEvan Yan char *buf, *curr, *next; 1146*26947304SEvan Yan size_t len; 1147*26947304SEvan Yan 1148*26947304SEvan Yan /* Do nothing if options string is empty */ 1149*26947304SEvan Yan if ((len = strlen(options)) == 0) 1150*26947304SEvan Yan return; 1151*26947304SEvan Yan 1152*26947304SEvan Yan /* To avoid modifying the input string, make a copy on the stack */ 1153*26947304SEvan Yan if ((buf = (char *)alloca(len + 1)) == NULL) { 1154*26947304SEvan Yan (void) printf("%s\n", options); 1155*26947304SEvan Yan return; 1156*26947304SEvan Yan } 1157*26947304SEvan Yan (void) strlcpy(buf, options, len + 1); 1158*26947304SEvan Yan 1159*26947304SEvan Yan /* Iterate through each comma-separated name/value pair */ 1160*26947304SEvan Yan curr = buf; 1161*26947304SEvan Yan do { 1162*26947304SEvan Yan if ((next = strchr(curr, ',')) != NULL) { 1163*26947304SEvan Yan *next = '\0'; 1164*26947304SEvan Yan next++; 1165*26947304SEvan Yan } 1166*26947304SEvan Yan (void) printf("%s\n", curr); 1167*26947304SEvan Yan } while ((curr = next) != NULL); 1168*26947304SEvan Yan } 1169*26947304SEvan Yan 1170*26947304SEvan Yan /* 1171*26947304SEvan Yan * print_error() 1172*26947304SEvan Yan * 1173*26947304SEvan Yan * Common routine to print error numbers in an appropriate way. 1174*26947304SEvan Yan * Prints nothing if error code is 0. 1175*26947304SEvan Yan */ 1176*26947304SEvan Yan static void 1177*26947304SEvan Yan print_error(int error) 1178*26947304SEvan Yan { 1179*26947304SEvan Yan switch (error) { 1180*26947304SEvan Yan case 0: 1181*26947304SEvan Yan /* No error */ 1182*26947304SEvan Yan return; 1183*26947304SEvan Yan case EACCES: 1184*26947304SEvan Yan (void) fprintf(stderr, 1185*26947304SEvan Yan gettext("ERROR: operation not authorized.\n")); 1186*26947304SEvan Yan break; 1187*26947304SEvan Yan case EBADF: 1188*26947304SEvan Yan (void) fprintf(stderr, 1189*26947304SEvan Yan gettext("ERROR: hotplug service is not available.\n")); 1190*26947304SEvan Yan break; 1191*26947304SEvan Yan case EBUSY: 1192*26947304SEvan Yan (void) fprintf(stderr, 1193*26947304SEvan Yan gettext("ERROR: devices or resources are busy.\n")); 1194*26947304SEvan Yan break; 1195*26947304SEvan Yan case EEXIST: 1196*26947304SEvan Yan (void) fprintf(stderr, 1197*26947304SEvan Yan gettext("ERROR: resource already exists.\n")); 1198*26947304SEvan Yan break; 1199*26947304SEvan Yan case EFAULT: 1200*26947304SEvan Yan (void) fprintf(stderr, 1201*26947304SEvan Yan gettext("ERROR: internal failure in hotplug service.\n")); 1202*26947304SEvan Yan break; 1203*26947304SEvan Yan case EINVAL: 1204*26947304SEvan Yan (void) fprintf(stderr, 1205*26947304SEvan Yan gettext("ERROR: invalid arguments.\n")); 1206*26947304SEvan Yan break; 1207*26947304SEvan Yan case ENOENT: 1208*26947304SEvan Yan (void) fprintf(stderr, 1209*26947304SEvan Yan gettext("ERROR: there are no connections to display.\n")); 1210*26947304SEvan Yan (void) fprintf(stderr, 1211*26947304SEvan Yan gettext("(See hotplug(1m) for more information.)\n")); 1212*26947304SEvan Yan break; 1213*26947304SEvan Yan case ENXIO: 1214*26947304SEvan Yan (void) fprintf(stderr, 1215*26947304SEvan Yan gettext("ERROR: no such path or connection.\n")); 1216*26947304SEvan Yan break; 1217*26947304SEvan Yan case ENOMEM: 1218*26947304SEvan Yan (void) fprintf(stderr, 1219*26947304SEvan Yan gettext("ERROR: not enough memory.\n")); 1220*26947304SEvan Yan break; 1221*26947304SEvan Yan case ENOTSUP: 1222*26947304SEvan Yan (void) fprintf(stderr, 1223*26947304SEvan Yan gettext("ERROR: operation not supported.\n")); 1224*26947304SEvan Yan break; 1225*26947304SEvan Yan case EIO: 1226*26947304SEvan Yan (void) fprintf(stderr, 1227*26947304SEvan Yan gettext("ERROR: hardware or driver specific failure.\n")); 1228*26947304SEvan Yan break; 1229*26947304SEvan Yan default: 1230*26947304SEvan Yan (void) fprintf(stderr, gettext("ERROR: operation failed: %s\n"), 1231*26947304SEvan Yan strerror(error)); 1232*26947304SEvan Yan break; 1233*26947304SEvan Yan } 1234*26947304SEvan Yan } 1235*26947304SEvan Yan 1236*26947304SEvan Yan /* 1237*26947304SEvan Yan * state_atoi() 1238*26947304SEvan Yan * 1239*26947304SEvan Yan * Convert a hotplug state from a string to an integer. 1240*26947304SEvan Yan */ 1241*26947304SEvan Yan static int 1242*26947304SEvan Yan state_atoi(char *state) 1243*26947304SEvan Yan { 1244*26947304SEvan Yan int i; 1245*26947304SEvan Yan 1246*26947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++) 1247*26947304SEvan Yan if (strcasecmp(state, hpstates[i].state_str) == 0) 1248*26947304SEvan Yan return (hpstates[i].state); 1249*26947304SEvan Yan 1250*26947304SEvan Yan return (-1); 1251*26947304SEvan Yan } 1252*26947304SEvan Yan 1253*26947304SEvan Yan /* 1254*26947304SEvan Yan * state_itoa() 1255*26947304SEvan Yan * 1256*26947304SEvan Yan * Convert a hotplug state from an integer to a string. 1257*26947304SEvan Yan */ 1258*26947304SEvan Yan static char * 1259*26947304SEvan Yan state_itoa(int state) 1260*26947304SEvan Yan { 1261*26947304SEvan Yan static char unknown[] = "UNKNOWN"; 1262*26947304SEvan Yan int i; 1263*26947304SEvan Yan 1264*26947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++) 1265*26947304SEvan Yan if (state == hpstates[i].state) 1266*26947304SEvan Yan return (hpstates[i].state_str); 1267*26947304SEvan Yan 1268*26947304SEvan Yan return (unknown); 1269*26947304SEvan Yan } 1270*26947304SEvan Yan 1271*26947304SEvan Yan /* 1272*26947304SEvan Yan * valid_target() 1273*26947304SEvan Yan * 1274*26947304SEvan Yan * Check if a state is a valid target for a changestate command. 1275*26947304SEvan Yan */ 1276*26947304SEvan Yan static short 1277*26947304SEvan Yan valid_target(int state) 1278*26947304SEvan Yan { 1279*26947304SEvan Yan int i; 1280*26947304SEvan Yan 1281*26947304SEvan Yan for (i = 0; hpstates[i].state_str != NULL; i++) 1282*26947304SEvan Yan if (state == hpstates[i].state) 1283*26947304SEvan Yan return (hpstates[i].valid_target); 1284*26947304SEvan Yan 1285*26947304SEvan Yan return (0); 1286*26947304SEvan Yan } 1287