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