On 02/20/2017 12:25 PM, enh wrote:
> ping. dmesg -C/-c still broken; you can always apply your cleanup
> after this patch, when you have time...

Yeah, my bad. I have a reply window open for Daniel Levy's cut stuff too
apologizing for sitting on my own local changes there:

> $ git diff toys/*/cut.c tests/cut.test | diffstat 
>  tests/cut.test   |   33 ++++
>  toys/posix/cut.c |  373 
> +++++++++++++++++++++----------------------------------
>  2 files changed, 176 insertions(+), 230 deletions(-)

for months now without cycling back around to it.

I suppose what I should do is extract the patch, attach it to the reply
message acknowledging I committed the other patches I backed it out for,
and then... abandon it like I basically have every time I've declared
diff bankruptcy and started developing against a new "clean" checkout.
(I keep meaning to come back to stuff but after 4 years in some cases,
it ain't happening.)

I miss the days when $DAYJOB wasn't in perpetual crisis mode. The theory
behind tomorrow's ELC talk on my mkroot stuff is it forces me to get
mkroot in shape by turning it into a crisis with deadline attached,
which lets me ignore the other crises without deadlines attached. But of
course I'm _also_ supposed to be preparing a table demo the next day for
the Turtle boards we've been sitting on for a year now, in hopes of
forcing us to take preorders and commit to an availability date. (It's a
raspberry pi IIb form factor, all the same I/O devices in the same
layout so it fits in the same cases and everything, but it's got an
Xilinx Spartan 6 LX25 FPGA instead of an ARM SOC, so you load an open
processor bitstream into it to run Linux. Of course I'm demoing it with
j-core, and of course despite having the prototypes most of a year now
we hadn't implemented an HDMI text console until... hardware has a new
bitstream sitting in my inbox, kernel side driver they told me to write.
So I guess that's my tomorrow night. And trying to buy a small HDTV in
portland.)

Tell you what: here's the unfinished dmesg patch. I will probably never
look at it again. The theory was to have both the old and new APIs
extract a line at a time from their input and then submit it to a common
codepath that would color it appropriately upon output, that way the old
and new APIs would use 90% the same code.

And since you basically did a complete rewrite of dmesg that I haven't
had a chance to do the design changes I want on: I'm putting it back
into pending. (Not that this matters much to Android's build...)

Rob

P.S. If you can think of a way to implement tests/dmesg.test I'm all
ears. Even with the mkroot stuff, making that reproducible is tricksy.

P.P.S. An advantage of a --color command line option is I can test
colored output without having to write a program that implements its own
pseudo-terminal to collect the output.
diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c
index c88fe11..4aa1b15 100644
--- a/toys/lsb/dmesg.c
+++ b/toys/lsb/dmesg.c
@@ -5,7 +5,7 @@
  * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
 
 // We care that FLAG_c is 1, so keep c at the end.
-USE_DMESG(NEWTOY(dmesg, "w(follow)Ctrs#<1n#c[!tr]", TOYFLAG_BIN))
+USE_DMESG(NEWTOY(dmesg, "w(follow)Ctrs#<1n#<1>9c[!tr]", TOYFLAG_BIN))
 
 config DMESG
   bool "dmesg"
@@ -15,8 +15,8 @@ config DMESG
 
     Print or control the kernel ring buffer.
 
-    -C	Clear ring buffer without printing
-    -c	Clear ring buffer after printing
+    -C	Clear the ring buffer
+    -c	Clear the ring buffer after printing
     -n	Set kernel logging LEVEL (1-9)
     -r	Raw output (with <level markers>)
     -s	Show the last SIZE many bytes
@@ -35,24 +35,30 @@ GLOBALS(
   int color;
 )
 
-static int xklogctl(int type, char *buf, int len)
+static void color(int c)
+{
+  if (TT.color) printf("\033[%dm", c);
+}
+
+// Output lines appropriately colored
+static void dmesg_line(int level, long long usec, char *str)
 {
-  int rc = klogctl(type, buf, len);
 
-  if (rc<0) perror_exit("klogctl");
 
-  return rc;
 }
 
 // Use klogctl for reading if we're on a pre-3.5 kernel.
-static void legacy_mode() {
+static void syscall_mode() {
   char *data, *to, *from;
   int size;
 
   // Figure out how much data we need, and fetch it.
-  if (!(size = TT.size)) size = xklogctl(10, 0, 0);
+  size = TT.size;
+  if (!size && 1>(size = klogctl(10, 0, 0))) perror_exit("klogctl");;
   data = to = from = xmalloc(size+1);
-  data[size = xklogctl(3 + (toys.optflags & FLAG_c), data, size)] = 0;
+  size = klogctl(3 + (toys.optflags & FLAG_c), data, size);
+  if (size < 0) perror_exit("klogctl");
+  data[size] = 0;
 
   // Filter out level markers and optionally time markers
   if (!(toys.optflags & FLAG_r)) while ((from - data) < size) {
@@ -75,23 +81,19 @@ static void legacy_mode() {
   if (CFG_TOYBOX_FREE) free(data);
 }
 
-static void color(int c) {
-  if (TT.color) printf("\033[%dm", c);
-}
-
 void dmesg_main(void)
 {
-  // For -n just tell kernel which messages to keep.
-  if (toys.optflags & FLAG_n) {
-    xklogctl(8, 0, TT.level);
+  int fd;
 
+  // For -n just tell kernel to which messages to keep.
+  if (TT.level) {
+    if (klogctl(8, NULL, TT.level)) perror_exit("klogctl");
     return;
   }
 
   // For -C just tell kernel to throw everything out.
   if (toys.optflags & FLAG_C) {
-    xklogctl(5, 0, 0);
-
+    if (klogctl(5, NULL, 0)) perror_exit("klogctl");
     return;
   }
 
@@ -100,36 +102,39 @@ void dmesg_main(void)
   // http://kernel.org/doc/Documentation/ABI/testing/dev-kmsg
 
   // Each read returns one message. By default, we block when there are no
-  // more messages (--follow); O_NONBLOCK is needed for for usual behavior.
-  int fd = xopen("/dev/kmsg", O_RDONLY | ((toys.optflags&FLAG_w)?0:O_NONBLOCK));
-  while (1) {
+  // more messages (--follow); O_NONBLOCK is needed for usual behavior.
+  // If /dev/kmsg isn't there, we fall through to syscall.
+  fd = open("/dev/kmsg", O_RDONLY | ((toys.optflags&FLAG_w)?0:O_NONBLOCK));
+  for (;;) {
     char msg[8192]; // CONSOLE_EXT_LOG_MAX.
     unsigned long long time_us;
     int facpri, subsystem, pos;
     char *p, *text;
     ssize_t len;
 
-    // kmsg fails with EPIPE if we try to read while the buffer moves under
-    // us; the next read will succeed and return the next available entry.
-    do {
-      len = read(fd, msg, sizeof(msg));
-    } while (len == -1 && errno == EPIPE);
-    // All reads from kmsg fail if you're on a pre-3.5 kernel.
-    if (len == -1 && errno == EINVAL) {
-      close(fd);
-      return legacy_mode();
+    if (-1 == (len = read(fd, msg, sizeof(msg)))) {
+      // kmsg fails with EPIPE if we try to read while the buffer moves,
+      // because EAGAIN would have made too much sense.
+      if (errno == EPIPE) continue;
+      // All reads from kmsg fail if you're on a pre-3.5 kernel.
+      if (errno == EINVAL) {
+        close(fd);
+        return legacy_mode();
+      }
     }
     if (len <= 0) break;
-
     msg[len] = 0;
 
-    if (sscanf(msg, "%u,%*u,%llu,%*[^;];%n", &facpri, &time_us, &pos) != 2)
-      continue;
-
-    // Drop extras after end of message text.
+    // Format has csv prefix ending with ; and abitrary data after \n
+    pos = 0;
+    sscanf(msg, "%u,%*u,%llu,%*[^;];%n", &facpri, &time_us, &pos);
+    if (!pos) continue;
     text = msg + pos;
     if ((p = strchr(text, '\n'))) *p = 0;
 
+
+    dmesg_line(facpri, time_us, text);
+
     // Is there a subsystem? (The ": " is just a convention.)
     p = strstr(text, ": ");
     subsystem = p ? (p - text) : 0;
@@ -151,7 +156,7 @@ void dmesg_main(void)
       text += subsystem;
       color(0);
     }
-    if (!((facpri&7) <= 3)) xputs(text);
+    if (!((facpri&7) <= 3)) puts(text);
     else {
       color(31);
       printf("%s", text);
_______________________________________________
Toybox mailing list
Toybox@lists.landley.net
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to