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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
* lspci - written by Isaac Dunham
USE_LSPCI(NEWTOY(lspci, "emkn"USE_LSPCI_TEXT("@i:"), TOYFLAG_USR|TOYFLAG_BIN))
config LSPCI
bool "lspci"
default y
help
usage: lspci [-ekm]
List PCI devices.
-e Print all 6 digits in class
-k Print kernel driver
-m Machine readable format
config LSPCI_TEXT
bool "lspci readable output"
depends on LSPCI
default y
help
usage: lspci [-n] [-i FILE ]
-n Numeric output (repeat for readable and numeric)
-i PCI ID database (default /usr/share/misc/pci.ids)
*/
#define FOR_lspci
#include "toys.h"
GLOBALS(
char *i;
long n;
FILE *db;
)
static int do_lspci(struct dirtree *new)
{
char *p = toybuf, *vendor = toybuf+9, *device = toybuf+18,
driver[256], *vbig = 0, *dbig = 0, **fields;
int dirfd;
if (!new->parent) return DIRTREE_RECURSE;
// Parse data out of /proc
if (-1 == (dirfd = openat(dirtree_parentfd(new), new->name, O_RDONLY)))
return 0;
*driver = 0;
if (toys.optflags & FLAG_k)
readlinkat0(dirfd, "driver", driver, sizeof(driver));
for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) {
int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf);
*p = 0;
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;
}
close(dirfd);
// Lookup/display data from pci.ids?
if (CFG_LSPCI_TEXT && TT.db) {
if (TT.n != 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.n > 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.n != 1) {
if (!TT.i) TT.i = "/usr/share/misc/pci.ids";
if (!(TT.db = fopen(TT.i, "r"))) perror_msg("%s", TT.i);
}
dirtree_read("/sys/bus/pci/devices", do_lspci);
}
|