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