xref: /illumos-gate/usr/src/cmd/pptadm/pptadm.c (revision eb9a1df2)
1*eb9a1df2SHans Rosenfeld /*
2*eb9a1df2SHans Rosenfeld  * This file and its contents are supplied under the terms of the
3*eb9a1df2SHans Rosenfeld  * Common Development and Distribution License ("CDDL"), version 1.0.
4*eb9a1df2SHans Rosenfeld  * You may only use this file in accordance with the terms of version
5*eb9a1df2SHans Rosenfeld  * 1.0 of the CDDL.
6*eb9a1df2SHans Rosenfeld  *
7*eb9a1df2SHans Rosenfeld  * A full copy of the text of the CDDL should have accompanied this
8*eb9a1df2SHans Rosenfeld  * source.  A copy of the CDDL is also available via the Internet at
9*eb9a1df2SHans Rosenfeld  * http://www.illumos.org/license/CDDL.
10*eb9a1df2SHans Rosenfeld  *
11*eb9a1df2SHans Rosenfeld  * Copyright 2018 Joyent, Inc.
12*eb9a1df2SHans Rosenfeld  */
13*eb9a1df2SHans Rosenfeld 
14*eb9a1df2SHans Rosenfeld #include <stdlib.h>
15*eb9a1df2SHans Rosenfeld #include <stdarg.h>
16*eb9a1df2SHans Rosenfeld #include <getopt.h>
17*eb9a1df2SHans Rosenfeld #include <string.h>
18*eb9a1df2SHans Rosenfeld #include <ofmt.h>
19*eb9a1df2SHans Rosenfeld #include <err.h>
20*eb9a1df2SHans Rosenfeld 
21*eb9a1df2SHans Rosenfeld #include <libppt.h>
22*eb9a1df2SHans Rosenfeld 
23*eb9a1df2SHans Rosenfeld typedef enum field {
24*eb9a1df2SHans Rosenfeld 	PPT_DEV,
25*eb9a1df2SHans Rosenfeld 	PPT_VENDOR,
26*eb9a1df2SHans Rosenfeld 	PPT_DEVICE,
27*eb9a1df2SHans Rosenfeld 	PPT_SUBVENDOR,
28*eb9a1df2SHans Rosenfeld 	PPT_SUBDEVICE,
29*eb9a1df2SHans Rosenfeld 	PPT_REV,
30*eb9a1df2SHans Rosenfeld 	PPT_PATH,
31*eb9a1df2SHans Rosenfeld 	PPT_LABEL
32*eb9a1df2SHans Rosenfeld } field_t;
33*eb9a1df2SHans Rosenfeld 
34*eb9a1df2SHans Rosenfeld const char *valname[] = {
35*eb9a1df2SHans Rosenfeld 	"dev",
36*eb9a1df2SHans Rosenfeld 	"vendor-id",
37*eb9a1df2SHans Rosenfeld 	"device-id",
38*eb9a1df2SHans Rosenfeld 	"subsystem-vendor-id",
39*eb9a1df2SHans Rosenfeld 	"subsystem-id",
40*eb9a1df2SHans Rosenfeld 	"revision-id",
41*eb9a1df2SHans Rosenfeld 	"path",
42*eb9a1df2SHans Rosenfeld 	"label"
43*eb9a1df2SHans Rosenfeld };
44*eb9a1df2SHans Rosenfeld 
45*eb9a1df2SHans Rosenfeld static ofmt_cb_t print_field;
46*eb9a1df2SHans Rosenfeld 
47*eb9a1df2SHans Rosenfeld static ofmt_field_t fields[] = {
48*eb9a1df2SHans Rosenfeld /* name,	field width, index, callback */
49*eb9a1df2SHans Rosenfeld { "DEV",	sizeof ("/dev/pptXX"), PPT_DEV, print_field },
50*eb9a1df2SHans Rosenfeld { "VENDOR",	sizeof ("VENDOR"), PPT_VENDOR, print_field },
51*eb9a1df2SHans Rosenfeld { "DEVICE",	sizeof ("DEVICE"), PPT_DEVICE, print_field },
52*eb9a1df2SHans Rosenfeld { "SUBVENDOR",	sizeof ("SUBVENDOR"), PPT_SUBVENDOR, print_field },
53*eb9a1df2SHans Rosenfeld { "SUBDEVICE",	sizeof ("SUBDEVICE"), PPT_SUBDEVICE, print_field },
54*eb9a1df2SHans Rosenfeld { "REV",	sizeof ("REV"), PPT_REV, print_field },
55*eb9a1df2SHans Rosenfeld { "PATH",	50, PPT_PATH, print_field },
56*eb9a1df2SHans Rosenfeld { "LABEL",	60, PPT_LABEL, print_field },
57*eb9a1df2SHans Rosenfeld { NULL,		0, 0, NULL },
58*eb9a1df2SHans Rosenfeld };
59*eb9a1df2SHans Rosenfeld 
60*eb9a1df2SHans Rosenfeld static void
usage(const char * errmsg)61*eb9a1df2SHans Rosenfeld usage(const char *errmsg)
62*eb9a1df2SHans Rosenfeld {
63*eb9a1df2SHans Rosenfeld 	if (errmsg != NULL)
64*eb9a1df2SHans Rosenfeld 		(void) fprintf(stderr, "pptadm: %s\n", errmsg);
65*eb9a1df2SHans Rosenfeld 	(void) fprintf(errmsg != NULL ? stderr : stdout,
66*eb9a1df2SHans Rosenfeld 	    "Usage:\n"
67*eb9a1df2SHans Rosenfeld 	    "pptadm list [ -j ]\n"
68*eb9a1df2SHans Rosenfeld 	    "pptadm list [-ap] [-o fields]\n");
69*eb9a1df2SHans Rosenfeld 	exit(errmsg != NULL ? EXIT_FAILURE : EXIT_SUCCESS);
70*eb9a1df2SHans Rosenfeld }
71*eb9a1df2SHans Rosenfeld 
72*eb9a1df2SHans Rosenfeld /* PRINTFLIKE1 */
73*eb9a1df2SHans Rosenfeld static void
die(const char * fmt,...)74*eb9a1df2SHans Rosenfeld die(const char *fmt, ...)
75*eb9a1df2SHans Rosenfeld {
76*eb9a1df2SHans Rosenfeld 	va_list ap;
77*eb9a1df2SHans Rosenfeld 	va_start(ap, fmt);
78*eb9a1df2SHans Rosenfeld 	verrx(EXIT_FAILURE, fmt, ap);
79*eb9a1df2SHans Rosenfeld 	va_end(ap);
80*eb9a1df2SHans Rosenfeld }
81*eb9a1df2SHans Rosenfeld 
82*eb9a1df2SHans Rosenfeld static boolean_t
print_field(ofmt_arg_t * arg,char * buf,uint_t bufsize)83*eb9a1df2SHans Rosenfeld print_field(ofmt_arg_t *arg, char *buf, uint_t bufsize)
84*eb9a1df2SHans Rosenfeld {
85*eb9a1df2SHans Rosenfeld 	nvlist_t *nvl = arg->ofmt_cbarg;
86*eb9a1df2SHans Rosenfeld 	nvpair_t *nvp = NULL;
87*eb9a1df2SHans Rosenfeld 
88*eb9a1df2SHans Rosenfeld 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
89*eb9a1df2SHans Rosenfeld 		const char *name = nvpair_name(nvp);
90*eb9a1df2SHans Rosenfeld 		char *val = NULL;
91*eb9a1df2SHans Rosenfeld 
92*eb9a1df2SHans Rosenfeld 		(void) nvpair_value_string(nvp, &val);
93*eb9a1df2SHans Rosenfeld 
94*eb9a1df2SHans Rosenfeld 		if (strcmp(name, valname[arg->ofmt_id]) != 0)
95*eb9a1df2SHans Rosenfeld 			continue;
96*eb9a1df2SHans Rosenfeld 
97*eb9a1df2SHans Rosenfeld 		(void) snprintf(buf, bufsize, "%s", val);
98*eb9a1df2SHans Rosenfeld 		return (B_TRUE);
99*eb9a1df2SHans Rosenfeld 	}
100*eb9a1df2SHans Rosenfeld 
101*eb9a1df2SHans Rosenfeld 	(void) snprintf(buf, bufsize, "--");
102*eb9a1df2SHans Rosenfeld 	return (B_TRUE);
103*eb9a1df2SHans Rosenfeld }
104*eb9a1df2SHans Rosenfeld 
105*eb9a1df2SHans Rosenfeld static int
list(int argc,char * argv[])106*eb9a1df2SHans Rosenfeld list(int argc, char *argv[])
107*eb9a1df2SHans Rosenfeld {
108*eb9a1df2SHans Rosenfeld 	const char *fields_str = NULL;
109*eb9a1df2SHans Rosenfeld 	boolean_t parsable = B_FALSE;
110*eb9a1df2SHans Rosenfeld 	boolean_t json = B_FALSE;
111*eb9a1df2SHans Rosenfeld 	boolean_t all = B_FALSE;
112*eb9a1df2SHans Rosenfeld 	uint_t ofmtflags = 0;
113*eb9a1df2SHans Rosenfeld 	ofmt_status_t oferr;
114*eb9a1df2SHans Rosenfeld 	ofmt_handle_t ofmt;
115*eb9a1df2SHans Rosenfeld 	int opt;
116*eb9a1df2SHans Rosenfeld 
117*eb9a1df2SHans Rosenfeld 	while ((opt = getopt(argc, argv, "ahjo:p")) != -1) {
118*eb9a1df2SHans Rosenfeld 		switch (opt) {
119*eb9a1df2SHans Rosenfeld 		case 'a':
120*eb9a1df2SHans Rosenfeld 			all = B_TRUE;
121*eb9a1df2SHans Rosenfeld 			break;
122*eb9a1df2SHans Rosenfeld 		case 'h':
123*eb9a1df2SHans Rosenfeld 			usage(NULL);
124*eb9a1df2SHans Rosenfeld 			break;
125*eb9a1df2SHans Rosenfeld 		case 'j':
126*eb9a1df2SHans Rosenfeld 			json = B_TRUE;
127*eb9a1df2SHans Rosenfeld 			break;
128*eb9a1df2SHans Rosenfeld 		case 'o':
129*eb9a1df2SHans Rosenfeld 			fields_str = optarg;
130*eb9a1df2SHans Rosenfeld 			break;
131*eb9a1df2SHans Rosenfeld 		case 'p':
132*eb9a1df2SHans Rosenfeld 			ofmtflags |= OFMT_PARSABLE;
133*eb9a1df2SHans Rosenfeld 			parsable = B_TRUE;
134*eb9a1df2SHans Rosenfeld 			break;
135*eb9a1df2SHans Rosenfeld 		default:
136*eb9a1df2SHans Rosenfeld 			usage("unrecognized option");
137*eb9a1df2SHans Rosenfeld 			break;
138*eb9a1df2SHans Rosenfeld 		}
139*eb9a1df2SHans Rosenfeld 	}
140*eb9a1df2SHans Rosenfeld 
141*eb9a1df2SHans Rosenfeld 	if (optind == (argc - 1))
142*eb9a1df2SHans Rosenfeld 		usage("unused arguments");
143*eb9a1df2SHans Rosenfeld 
144*eb9a1df2SHans Rosenfeld 	if (json && (parsable || fields_str != NULL))
145*eb9a1df2SHans Rosenfeld 		usage("-j option cannot be used with -p or -o options");
146*eb9a1df2SHans Rosenfeld 
147*eb9a1df2SHans Rosenfeld 	if (fields_str == NULL) {
148*eb9a1df2SHans Rosenfeld 		if (parsable)
149*eb9a1df2SHans Rosenfeld 			usage("-o must be provided when using -p option");
150*eb9a1df2SHans Rosenfeld 		fields_str = "dev,vendor,device,path";
151*eb9a1df2SHans Rosenfeld 	}
152*eb9a1df2SHans Rosenfeld 
153*eb9a1df2SHans Rosenfeld 	oferr = ofmt_open(fields_str, fields, ofmtflags, 0, &ofmt);
154*eb9a1df2SHans Rosenfeld 
155*eb9a1df2SHans Rosenfeld 	ofmt_check(oferr, parsable, ofmt, die, warn);
156*eb9a1df2SHans Rosenfeld 
157*eb9a1df2SHans Rosenfeld 	nvlist_t *nvl = all ? ppt_list() : ppt_list_assigned();
158*eb9a1df2SHans Rosenfeld 	nvpair_t *nvp = NULL;
159*eb9a1df2SHans Rosenfeld 
160*eb9a1df2SHans Rosenfeld 	if (json) {
161*eb9a1df2SHans Rosenfeld 		if (printf("{\n\t\"devices\": [\n") < 0)
162*eb9a1df2SHans Rosenfeld 			err(EXIT_FAILURE, "failed to write JSON");
163*eb9a1df2SHans Rosenfeld 	}
164*eb9a1df2SHans Rosenfeld 
165*eb9a1df2SHans Rosenfeld 	while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
166*eb9a1df2SHans Rosenfeld 		nvlist_t *props;
167*eb9a1df2SHans Rosenfeld 
168*eb9a1df2SHans Rosenfeld 		(void) nvpair_value_nvlist(nvp, &props);
169*eb9a1df2SHans Rosenfeld 
170*eb9a1df2SHans Rosenfeld 		if (json) {
171*eb9a1df2SHans Rosenfeld 			if (printf("\t\t") < 0)
172*eb9a1df2SHans Rosenfeld 				err(EXIT_FAILURE, "failed to write JSON");
173*eb9a1df2SHans Rosenfeld 			if (nvlist_print_json(stdout, props) < 0)
174*eb9a1df2SHans Rosenfeld 				err(EXIT_FAILURE, "failed to write JSON");
175*eb9a1df2SHans Rosenfeld 			if (nvlist_next_nvpair(nvl, nvp) != NULL)
176*eb9a1df2SHans Rosenfeld 				(void) printf(",\n");
177*eb9a1df2SHans Rosenfeld 		} else {
178*eb9a1df2SHans Rosenfeld 			ofmt_print(ofmt, props);
179*eb9a1df2SHans Rosenfeld 		}
180*eb9a1df2SHans Rosenfeld 	}
181*eb9a1df2SHans Rosenfeld 
182*eb9a1df2SHans Rosenfeld 	if (json) {
183*eb9a1df2SHans Rosenfeld 		if (printf("\n\t]\n}\n") < 0)
184*eb9a1df2SHans Rosenfeld 			err(EXIT_FAILURE, "failed to write JSON");
185*eb9a1df2SHans Rosenfeld 	}
186*eb9a1df2SHans Rosenfeld 
187*eb9a1df2SHans Rosenfeld 	nvlist_free(nvl);
188*eb9a1df2SHans Rosenfeld 	ofmt_close(ofmt);
189*eb9a1df2SHans Rosenfeld 	return (EXIT_SUCCESS);
190*eb9a1df2SHans Rosenfeld }
191*eb9a1df2SHans Rosenfeld 
192*eb9a1df2SHans Rosenfeld int
main(int argc,char * argv[])193*eb9a1df2SHans Rosenfeld main(int argc, char *argv[])
194*eb9a1df2SHans Rosenfeld {
195*eb9a1df2SHans Rosenfeld 	if (argc == 1)
196*eb9a1df2SHans Rosenfeld 		return (list(argc - 1, argv));
197*eb9a1df2SHans Rosenfeld 
198*eb9a1df2SHans Rosenfeld 	if (strcmp(argv[1], "list") == 0) {
199*eb9a1df2SHans Rosenfeld 		return (list(argc - 1, &argv[1]));
200*eb9a1df2SHans Rosenfeld 	} else {
201*eb9a1df2SHans Rosenfeld 		usage("unknown sub-command");
202*eb9a1df2SHans Rosenfeld 	}
203*eb9a1df2SHans Rosenfeld 
204*eb9a1df2SHans Rosenfeld 	return (EXIT_SUCCESS);
205*eb9a1df2SHans Rosenfeld }
206