1 /* 2 * lspci - written by Isaac Dunham 3 4 USE_LSPCI(NEWTOY(lspci, "emkn"USE_LSPCI_TEXT("@i:"), TOYFLAG_USR|TOYFLAG_BIN)) 5 6 config LSPCI 7 bool "lspci" 8 default y 9 help 10 usage: lspci [-ekm] 11 12 List PCI devices. 13 14 -e Print all 6 digits in class 15 -k Print kernel driver 16 -m Machine parseable format 17 18 config LSPCI_TEXT 19 bool "lspci readable output" 20 depends on LSPCI 21 default y 22 help 23 usage: lspci [-n] [-i FILE ] 24 25 -n Numeric output (repeat for readable and numeric) 26 -i PCI ID database (default /usr/share/misc/pci.ids) 27 28 */ 29 30 #define FOR_lspci 31 #include "toys.h" 32 33 GLOBALS( 34 char *ids; 35 long numeric; 36 37 FILE *db; 38 ) 39 40 int do_lspci(struct dirtree *new) 41 { 42 char *p = toybuf, *vendor = toybuf+9, *device = toybuf+18, 43 driver[256], *vbig = 0, *dbig = 0, **fields; 44 int dirfd; 45 46 if (!new->parent) return DIRTREE_RECURSE; 47 48 // Parse data out of /proc 49 50 if (-1 == (dirfd = openat(dirtree_parentfd(new), new->name, O_RDONLY))) 51 return 0; 52 53 // it's ok for the driver link not to be there, whatever fortify says 54 *driver = 0; 55 if (toys.optflags & FLAG_k) 56 if (readlinkat(dirfd, "driver", driver, sizeof(driver))) {}; 57 58 for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) { 59 int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf); 60 *p = 0; 61 62 if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) { 63 close(dirfd); 64 return 0; 65 } 66 xreadall(fd, p, size); 67 memmove(p, p+2, size -= 2); 68 p[size] = 0; 69 close(fd); 70 p += 9; 71 } 72 73 close(dirfd); 74 75 // Lookup/display data from pci.ids? 76 77 if (CFG_LSPCI_TEXT && TT.db) { 78 if (TT.numeric != 1) { 79 char *s; 80 81 fseek(TT.db, 0, SEEK_SET); 82 while (!vbig || !dbig) { 83 s = p; 84 if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break; 85 while (isspace(*s)) s++; 86 if (*s == '#') continue; 87 if (vbig && s == p) break; 88 if (strstart(&s, vbig ? device : vendor)) { 89 if (vbig) dbig = s+2; 90 else vbig = s+2; 91 s += strlen(s); 92 s[-1] = 0; // trim ending newline 93 p = s + 1; 94 } 95 } 96 } 97 98 if (TT.numeric > 1) { 99 printf((toys.optflags & FLAG_m) 100 ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\"" 101 : "%s Class %s: %s [%s] %s [%s]", 102 new->name+5, toybuf, vbig ? vbig : "", vendor, 103 dbig ? dbig : "", device); 104 105 goto driver; 106 } 107 } 108 109 printf((toys.optflags & FLAG_m) ? "%s \"%s\" \"%s\" \"%s\"" 110 : "%s Class %s: %s:%s", new->name+5, toybuf, 111 vbig ? vbig : vendor, dbig ? dbig : device); 112 113 driver: 114 if (*driver) 115 printf((toys.optflags & FLAG_m) ? " \"%s\"" : " %s", basename(driver)); 116 xputc('\n'); 117 118 return 0; 119 } 120 121 void lspci_main(void) 122 { 123 if (CFG_LSPCI_TEXT && TT.numeric != 1) { 124 if (!TT.ids) TT.ids = "/usr/share/misc/pci.ids"; 125 if (!(TT.db = fopen(TT.ids, "r"))) 126 perror_msg("could not open PCI ID db"); 127 } 128 129 dirtree_read("/sys/bus/pci/devices", do_lspci); 130 } 131