aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2014-08-11 20:11:58 -0500
committerRob Landley <rob@landley.net>2014-08-11 20:11:58 -0500
commit32a3a0806403d5bd652df1a8fefc318c7812ddca (patch)
treee5b18f5ad26e22c606076ecf9d3f23c19d0129fe
parent579ce3511a9bd9f288201c16553c866384e14a79 (diff)
downloadtoybox-32a3a0806403d5bd652df1a8fefc318c7812ddca.tar.gz
Cleanup pass on lspci.
-rw-r--r--toys/pending/lspci.c159
1 files changed, 67 insertions, 92 deletions
diff --git a/toys/pending/lspci.c b/toys/pending/lspci.c
index aef40d8b..7361ca14 100644
--- a/toys/pending/lspci.c
+++ b/toys/pending/lspci.c
@@ -11,7 +11,7 @@ config LSPCI
List PCI devices.
- -e Print all 6 digits in class (like elspci)
+ -e Print all 6 digits in class
-k Print kernel driver
-m Machine parseable format
@@ -37,117 +37,92 @@ GLOBALS(
FILE *db;
)
-char *id_check_match(char *id, char *buf)
-{
- int i = 0;
-
- while (id[i]) {
- if (id[i] == buf[i]) i++;
- else return 0;
- }
-
- return buf + i + 2;
-}
-
-/*
- * In: vendid, devid, fil
- * Out: vname, devname
- * Out must be zeroed before use.
- * vmame and devname must be char[256], zeroed out
- * Returns (2 - number of IDs matched): vendor must be matched for
- * dev to be matched
- */
-int find_in_db(char *vendid, char *devid, FILE *fil, char *vname, char *devname)
-{
- char buf[256], *vtext = 0L, *dtext = 0L;
-
- fseek(fil, 0, SEEK_SET);
- while (!*vname) {
- //loop through
- if (!fgets(buf, 255, fil)) return 2;
- if ((vtext = id_check_match(vendid, buf)))
- strncpy(vname, vtext, strlen(vtext) - 1);
- }
- while (!*devname) {
- if (!fgets(buf, 255, fil) || (*buf != '\t' && *buf != '#')) return 1;
- if (*buf == '#') continue;
- if ((dtext = id_check_match(devid, buf + 1)))
- strncpy(devname, dtext, strlen(dtext) - 1);
- }
-
- // matched both
- return 0;
-}
-
int do_lspci(struct dirtree *new)
{
- int alen = 8, dirfd, res = 2; //no textual descriptions read
- char *dname = dirtree_path(new, &alen);
-
- memset(toybuf, 0, 4096);
- struct {
- char class[16], vendor[16], device[16], module[256],
- vname[256], devname[256];
- } *bufs = (void*)(toybuf + 2);
+ char *p = toybuf, *vendor = toybuf+9, *device = toybuf+18,
+ driver[256], *vbig = 0, *dbig = 0, **fields;
+ int dirfd;
if (!new->parent) return DIRTREE_RECURSE;
- errno = 0;
- dirfd = open(dname, O_RDONLY);
- if (dirfd > 0) {
- char *p, **fields = (char*[]){"class", "vendor", "device", ""};
- for (p = toybuf; **fields; p+=16, fields++) {
- int fd, size = ((toys.optflags & FLAG_e) && p == toybuf) ? 8 : 6;
+ // Parse data out of /proc
- if ((fd = openat(dirfd, *fields, O_RDONLY)) < 0) continue;
- xread(fd, p, size);
- close(fd);
+ if (-1 == (dirfd = openat(dirtree_parentfd(new), new->name, O_RDONLY)))
+ return 0;
- p[size] = 0;
- }
+ *driver = 0;
+ if (toys.optflags & FLAG_k)
+ readlinkat(dirfd, "driver", driver, sizeof(driver));
- close(dirfd);
- if (errno) return 0;
+ for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) {
+ int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf);
+ *p = 0;
- {
- char *driver = "";
- char *fmt = (toys.optflags & FLAG_m) ? "%s, \"%s\" \"%s\" \"%s\" \"%s\"\n"
- : "%s Class %s: %s:%s %s\n";
+ if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) {
+ close(dirfd);
+ return 0;
+ }
+ xreadall(fd, p, size);
+ memmove(p, p+2, size -= 2);
+ p[size] = 0;
+ close(fd);
+ p += 9;
+ }
- if (toys.optflags & FLAG_k) {
- strcat(dname, "/driver");
- if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1)
- driver = basename(bufs->module);
- }
- if (CFG_LSPCI_TEXT && TT.numeric != 1) {
- res = find_in_db(bufs->vendor, bufs->device, TT.db,
- bufs->vname, bufs->devname);
- }
- if (CFG_LSPCI_TEXT && TT.numeric > 1) {
- fmt = (toys.optflags & FLAG_m)
- ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\" \"%s\"\n"
- : "%s Class %s: %s [%s] %s [%s] %s\n";
- printf(fmt, new->name + 5, bufs->class, bufs->vname, bufs->vendor,
- bufs->devname, bufs->device, driver);
- } else {
- printf(fmt, new->name + 5, bufs->class,
- (res < 2) ? bufs->vname : bufs->vendor,
- !(res) ? bufs->devname : bufs->device, driver);
+ close(dirfd);
+
+ // Lookup/display data from pci.ids?
+
+ if (CFG_LSPCI_TEXT && TT.db) {
+ if (TT.numeric != 1) {
+ char *s;
+
+ fseek(TT.db, 0, SEEK_SET);
+ while (!vbig || !dbig) {
+ s = p;
+ if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break;
+ while (isspace(*s)) s++;
+ if (*s == '#') continue;
+ if (vbig && s == p) break;
+ if (strstart(&s, vbig ? device : vendor)) {
+ if (vbig) dbig = s+2;
+ else vbig = s+2;
+ s += strlen(s);
+ s[-1] = 0; // trim ending newline
+ p = s + 1;
+ }
}
}
+
+ if (TT.numeric > 1) {
+ printf((toys.optflags & FLAG_m)
+ ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\""
+ : "%s Class %s: %s [%s] %s [%s]",
+ new->name+5, toybuf, vbig ? vbig : "", vendor,
+ dbig ? dbig : "", device);
+
+ goto driver;
+ }
}
+ printf((toys.optflags & FLAG_m) ? "%s \"%s\" \"%s\" \"%s\""
+ : "%s Class %s: %s:%s", new->name+5, toybuf,
+ vbig ? vbig : vendor, dbig ? dbig : device);
+
+driver:
+ if (*driver)
+ printf((toys.optflags & FLAG_m) ? " \"%s\"" : " %s", basename(driver));
+ xputc('\n');
+
return 0;
}
void lspci_main(void)
{
if (CFG_LSPCI_TEXT && TT.numeric != 1) {
- TT.db = fopen(TT.ids ? TT.ids : "/usr/share/misc/pci.ids", "r");
- if (errno) {
- TT.numeric = 1;
- error_msg("could not open PCI ID db");
- }
+ if (!TT.ids) TT.ids = "/usr/share/misc/pci.ids";
+ if (!(TT.db = fopen(TT.ids, "r")))
+ perror_msg("could not open PCI ID db");
}
dirtree_read("/sys/bus/pci/devices", do_lspci);