#include <stdlib.h>
#include <stdarg.h>
#include <getopt.h>
#include <string.h>
#include <ofmt.h>
#include <err.h>
#include <libppt.h>
typedef enum field {
PPT_DEV,
PPT_VENDOR,
PPT_DEVICE,
PPT_SUBVENDOR,
PPT_SUBDEVICE,
PPT_REV,
PPT_PATH,
PPT_LABEL
} field_t;
const char *valname[] = {
"dev",
"vendor-id",
"device-id",
"subsystem-vendor-id",
"subsystem-id",
"revision-id",
"path",
"label"
};
static ofmt_cb_t print_field;
static ofmt_field_t fields[] = {
{ "DEV", sizeof ("/dev/pptXX"), PPT_DEV, print_field },
{ "VENDOR", sizeof ("VENDOR"), PPT_VENDOR, print_field },
{ "DEVICE", sizeof ("DEVICE"), PPT_DEVICE, print_field },
{ "SUBVENDOR", sizeof ("SUBVENDOR"), PPT_SUBVENDOR, print_field },
{ "SUBDEVICE", sizeof ("SUBDEVICE"), PPT_SUBDEVICE, print_field },
{ "REV", sizeof ("REV"), PPT_REV, print_field },
{ "PATH", 50, PPT_PATH, print_field },
{ "LABEL", 60, PPT_LABEL, print_field },
{ NULL, 0, 0, NULL },
};
static void
usage(const char *errmsg)
{
if (errmsg != NULL)
(void) fprintf(stderr, "pptadm: %s\n", errmsg);
(void) fprintf(errmsg != NULL ? stderr : stdout,
"Usage:\n"
"pptadm list [ -j ]\n"
"pptadm list [-ap] [-o fields]\n");
exit(errmsg != NULL ? EXIT_FAILURE : EXIT_SUCCESS);
}
static void
die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
verrx(EXIT_FAILURE, fmt, ap);
va_end(ap);
}
static boolean_t
print_field(ofmt_arg_t *arg, char *buf, uint_t bufsize)
{
nvlist_t *nvl = arg->ofmt_cbarg;
nvpair_t *nvp = NULL;
while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
const char *name = nvpair_name(nvp);
char *val = NULL;
(void) nvpair_value_string(nvp, &val);
if (strcmp(name, valname[arg->ofmt_id]) != 0)
continue;
(void) snprintf(buf, bufsize, "%s", val);
return (B_TRUE);
}
(void) snprintf(buf, bufsize, "--");
return (B_TRUE);
}
static int
list(int argc, char *argv[])
{
const char *fields_str = NULL;
boolean_t parsable = B_FALSE;
boolean_t json = B_FALSE;
boolean_t all = B_FALSE;
uint_t ofmtflags = 0;
ofmt_status_t oferr;
ofmt_handle_t ofmt;
int opt;
while ((opt = getopt(argc, argv, "ahjo:p")) != -1) {
switch (opt) {
case 'a':
all = B_TRUE;
break;
case 'h':
usage(NULL);
break;
case 'j':
json = B_TRUE;
break;
case 'o':
fields_str = optarg;
break;
case 'p':
ofmtflags |= OFMT_PARSABLE;
parsable = B_TRUE;
break;
default:
usage("unrecognized option");
break;
}
}
if (optind == (argc - 1))
usage("unused arguments");
if (json && (parsable || fields_str != NULL))
usage("-j option cannot be used with -p or -o options");
if (fields_str == NULL) {
if (parsable)
usage("-o must be provided when using -p option");
fields_str = "dev,vendor,device,path";
}
oferr = ofmt_open(fields_str, fields, ofmtflags, 0, &ofmt);
ofmt_check(oferr, parsable, ofmt, die, warn);
nvlist_t *nvl = all ? ppt_list() : ppt_list_assigned();
nvpair_t *nvp = NULL;
if (json) {
if (printf("{\n\t\"devices\": [\n") < 0)
err(EXIT_FAILURE, "failed to write JSON");
}
while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
nvlist_t *props;
(void) nvpair_value_nvlist(nvp, &props);
if (json) {
if (printf("\t\t") < 0)
err(EXIT_FAILURE, "failed to write JSON");
if (nvlist_print_json(stdout, props) < 0)
err(EXIT_FAILURE, "failed to write JSON");
if (nvlist_next_nvpair(nvl, nvp) != NULL)
(void) printf(",\n");
} else {
ofmt_print(ofmt, props);
}
}
if (json) {
if (printf("\n\t]\n}\n") < 0)
err(EXIT_FAILURE, "failed to write JSON");
}
nvlist_free(nvl);
ofmt_close(ofmt);
return (EXIT_SUCCESS);
}
int
main(int argc, char *argv[])
{
if (argc == 1)
return (list(argc - 1, argv));
if (strcmp(argv[1], "list") == 0) {
return (list(argc - 1, &argv[1]));
} else {
usage("unknown sub-command");
}
return (EXIT_SUCCESS);
}