OSDN Git Service

Add missing liblog dependency
[android-x86/external-toybox.git] / toys / other / lspci.c
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 static 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   *driver = 0;
54   if (toys.optflags & FLAG_k)
55     readlinkat0(dirfd, "driver", driver, sizeof(driver));
56
57   for (fields = (char*[]){"class", "vendor", "device", 0}; *fields; fields++) {
58     int fd, size = 6 + 2*((toys.optflags & FLAG_e) && p == toybuf);
59     *p = 0;
60
61     if (-1 == (fd = openat(dirfd, *fields, O_RDONLY))) {
62       close(dirfd);
63       return 0;
64     }
65     xreadall(fd, p, size);
66     memmove(p, p+2, size -= 2);
67     p[size] = 0;
68     close(fd);
69     p += 9;
70   }
71
72   close(dirfd);
73
74   // Lookup/display data from pci.ids?
75
76   if (CFG_LSPCI_TEXT && TT.db) {
77     if (TT.numeric != 1) {
78       char *s;
79
80       fseek(TT.db, 0, SEEK_SET);
81       while (!vbig || !dbig) {
82         s = p;
83         if (!fgets(s, sizeof(toybuf)-(p-toybuf)-1, TT.db)) break;
84         while (isspace(*s)) s++;
85         if (*s == '#') continue;
86         if (vbig && s == p) break;
87         if (strstart(&s, vbig ? device : vendor)) {
88           if (vbig) dbig = s+2;
89           else vbig = s+2;
90           s += strlen(s);
91           s[-1] = 0; // trim ending newline
92           p = s + 1;
93         }
94       }
95     }
96
97     if (TT.numeric > 1) {
98       printf((toys.optflags & FLAG_m)
99         ? "%s, \"%s\" \"%s [%s]\" \"%s [%s]\""
100         : "%s Class %s: %s [%s] %s [%s]",
101         new->name+5, toybuf, vbig ? vbig : "", vendor,
102         dbig ? dbig : "", device);
103
104       goto driver;
105     }
106   }
107
108   printf((toys.optflags & FLAG_m) ? "%s \"%s\" \"%s\" \"%s\""
109     : "%s Class %s: %s:%s", new->name+5, toybuf, 
110     vbig ? vbig : vendor, dbig ? dbig : device);
111
112 driver:
113   if (*driver)
114     printf((toys.optflags & FLAG_m) ? " \"%s\"" : " %s", basename(driver));
115   xputc('\n');
116
117   return 0;
118 }
119
120 void lspci_main(void)
121 {
122   if (CFG_LSPCI_TEXT && TT.numeric != 1) {
123     if (!TT.ids) TT.ids = "/usr/share/misc/pci.ids";
124     if (!(TT.db = fopen(TT.ids, "r"))) perror_msg("%s", TT.ids);
125   }
126
127   dirtree_read("/sys/bus/pci/devices", do_lspci);
128 }