Home | History | Annotate | Download | only in other
      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   // 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