aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2017-01-04 10:45:55 -0800
committerRob Landley <rob@landley.net>2017-02-20 21:42:26 -0600
commit461b90c341090c46083e83ca59ccb88371e051e4 (patch)
tree98fc3da837953eb5c191c50b7059bbcb7530af3d
parentac22dfa9c751ca15c2cd90b6a702ebd960b202ee (diff)
downloadtoybox-461b90c341090c46083e83ca59ccb88371e051e4.tar.gz
Fix dmesg -c and -C.
I never use these, so I didn't notice I'd broken them until someone who does bringup complained. The "one weird trick" with SEEK_DATA is documented at the URL we already point to. SEEK_DATA was added in Linux 3.1 (2011) and isn't available in glibc 2.19 (2014), so I've added that to "portability.h" for the benefit of Ubuntu 14.04. Also make -c and -C mutually exclusive. Also fix some of the formatting I introduced earlier. (A clang-format file would help prevent these mistakes...)
-rw-r--r--lib/portability.h4
-rw-r--r--toys/lsb/dmesg.c44
2 files changed, 28 insertions, 20 deletions
diff --git a/lib/portability.h b/lib/portability.h
index afe02c1c..e0dd914e 100644
--- a/lib/portability.h
+++ b/lib/portability.h
@@ -45,6 +45,10 @@
#define RLIMIT_RTTIME 15
#endif
+#ifndef SEEK_DATA
+#define SEEK_DATA 3
+#endif
+
// We don't define GNU_dammit because we're not part of the gnu project, and
// don't want to get any FSF on us. Unfortunately glibc (gnu libc)
// won't give us Linux syscall wrappers without claiming to be part of the
diff --git a/toys/lsb/dmesg.c b/toys/lsb/dmesg.c
index c88fe113..a991e898 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#c[!tr][!Cc]", TOYFLAG_BIN))
config DMESG
bool "dmesg"
@@ -45,7 +45,8 @@ static int xklogctl(int type, char *buf, int len)
}
// Use klogctl for reading if we're on a pre-3.5 kernel.
-static void legacy_mode() {
+static void legacy_mode()
+{
char *data, *to, *from;
int size;
@@ -75,33 +76,23 @@ static void legacy_mode() {
if (CFG_TOYBOX_FREE) free(data);
}
-static void color(int c) {
+static void color(int c)
+{
if (TT.color) printf("\033[%dm", c);
}
-void dmesg_main(void)
+static void print_all(void)
{
- // For -n just tell kernel which messages to keep.
- if (toys.optflags & FLAG_n) {
- xklogctl(8, 0, TT.level);
-
- return;
- }
-
- // For -C just tell kernel to throw everything out.
- if (toys.optflags & FLAG_C) {
- xklogctl(5, 0, 0);
-
- return;
- }
-
- TT.color = isatty(1);
-
// 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));
+
+ // With /dev/kmsg, SYSLOG_ACTION_CLEAR (5) doesn't actually remove anything;
+ // you need to seek to the last clear point.
+ lseek(fd, 0, SEEK_DATA);
+
while (1) {
char msg[8192]; // CONSOLE_EXT_LOG_MAX.
unsigned long long time_us;
@@ -161,3 +152,16 @@ void dmesg_main(void)
}
close(fd);
}
+
+void dmesg_main(void)
+{
+ TT.color = isatty(1);
+
+ if (!(toys.optflags & (FLAG_C|FLAG_n))) print_all();
+
+ // Set the log level?
+ if (toys.optflags & FLAG_n) xklogctl(8, 0, TT.level);
+
+ // Clear the buffer?
+ if (toys.optflags & (FLAG_C|FLAG_c)) xklogctl(5, 0, 0);
+}