1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
/*
* lspci - written by Isaac Dunham
USE_LSPCI(NEWTOY(lspci, "emkns:", TOYFLAG_USR|TOYFLAG_BIN))
config LSPCI
bool "lspci"
default n
help
usage: lspci [-ekmn]
List PCI devices.
-e Print all 6 digits in class (like elspci)
-k Print kernel driver
-m Machine parseable format
-n Numeric output (default)
*/
#define FOR_lspci
#include "toys.h"
int do_lspci(struct dirtree *new)
{
int alen = 8, dirfd;
char *dname = dirtree_path(new, &alen);
struct {
char class[16], vendor[16], device[16], module[256];
} *bufs = (void*)(toybuf + 2);
if (!strcmp("/sys/bus/pci/devices", dname)) 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;
if ((fd = openat(dirfd, *fields, O_RDONLY)) < 0) continue;
size = ((toys.optflags & FLAG_e) && (p == toybuf)) ? 8 : 6;
p[read(fd, p, size)] = '\0';
close(fd);
}
close(dirfd);
if (!errno) {
char *driver = "";
char *fmt = toys.optflags & FLAG_m ? "%s, \"%s\" \"%s\" \"%s\" \"%s\"\n"
: "%s Class %s: %s:%s %s\n";
if (toys.optflags & FLAG_k) {
strcat(dname, "/driver");
if (readlink(dname, bufs->module, sizeof(bufs->module)) != -1)
driver = basename(bufs->module);
}
printf(fmt, new->name + 5, bufs->class, bufs->vendor, bufs->device,
driver);
}
}
return 0;
}
void lspci_main(void)
{
dirtree_read("/sys/bus/pci/devices", do_lspci);
}
|