diff toys/pending/lspci.c @ 990:8caeba551a28

This is the preliminary version of lspci text output support (the location of pci.ids is hard-coded to /usr/share/misc/pci.ids, as found on Debian/Ubuntu). +88 lines in two files, including reformatting, comments, whitespace, and build configuration as well as new code. The changes: -Add library code to look up descriptions. -Add a counter for -n (for the sake of -nn) -Add the file stream "db" to GLOBALS and open it conditionally -Add name fields to bufs -Look up text if enabled and -n is passed never or twice -Print text if lookup succeeded
author Isaac Dunham <idunham@lavabit.com>
date Wed, 07 Aug 2013 11:51:26 -0500
parents f84dd3473233
children 9b3818b2a054
line wrap: on
line diff
--- a/toys/pending/lspci.c	Mon Aug 05 13:16:03 2013 -0500
+++ b/toys/pending/lspci.c	Wed Aug 07 11:51:26 2013 -0500
@@ -1,29 +1,87 @@
 /*
  * lspci - written by Isaac Dunham
 
-USE_LSPCI(NEWTOY(lspci, "emkns:", TOYFLAG_USR|TOYFLAG_BIN))
+USE_LSPCI(NEWTOY(lspci, "emkn@", TOYFLAG_USR|TOYFLAG_BIN))
 
 config LSPCI
   bool "lspci"
   default n
   help
-    usage: lspci [-ekmn]
+    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)
+    -n  Numeric output
+
+config LSPCI_TEXT
+  bool "lspci readable output"
+  depends on LSPCI
+  default n
+  help
+    lspci without -n prints readable descriptions;
+    lspci -nn prints both readable and numeric description
 */
 #define FOR_lspci
 #include "toys.h"
+extern int find_in_db(char * , char * , FILE * , char * , char * );
+
+GLOBALS(
+long numeric;
+
+FILE * db;
+)
+
+char * id_check_match(char * id, char * buf)
+{
+  int i = 0;
+  while (id[i]) {
+    if (id[i] == buf[i]) {
+      i++;
+    } else {
+      return (char *)0L;
+    }
+  }
+  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)
+{
+  fseek(fil, 0, SEEK_SET);
+  char buf[256], *vtext = 0L, *dtext = 0L;
+  while (!(vname[0])) {
+    //loop through
+    if (fgets(buf, 255, fil)==NULL) return 2;
+    if ((vtext = id_check_match(vendid, buf)))
+      strncpy(vname, vtext, strlen(vtext) - 1);
+  }
+  while (!(devname[0])) {
+    if ((fgets(buf, 255, fil)==NULL) || (buf[0] != '\t' ))
+      return 1;
+    if ((dtext = id_check_match(devid, buf + 1)))
+      strncpy(devname, dtext, strlen(dtext) - 1);
+  }
+  return 0; /* Succeeded in matching both */
+}
 
 int do_lspci(struct dirtree *new)
 {
-  int alen = 8, dirfd;
+  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];
+    char class[16], vendor[16], device[16], module[256],
+    vname[256], devname[256];
   } *bufs = (void*)(toybuf + 2);
 
   if (!strcmp("/sys/bus/pci/devices", dname)) return DIRTREE_RECURSE;
@@ -52,8 +110,22 @@
         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);
+      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 == 2)) {
+        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);
+      }
+      
     }
   }
   return 0;
@@ -61,5 +133,13 @@
 
 void lspci_main(void)
 {
+  if (CFG_LSPCI_TEXT && (TT.numeric != 1)) {
+    TT.db = fopen("/usr/share/misc/pci.ids", "r");
+    if (errno) {
+      TT.numeric = 1;
+      error_msg("could not open PCI ID db");
+    }
+  }
+
   dirtree_read("/sys/bus/pci/devices", do_lspci);
 }