xref: /illumos-gate/usr/src/cmd/hotplug/hotplug.c (revision 26947304)
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