17aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley/* dmesg.c - display/control kernel ring buffer.
2b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley *
3fece5cb6d796119eccb1ae0074e5b3aaccbb74eeRob Landley * Copyright 2006, 2007 Rob Landley <rob@landley.net>
4fece5cb6d796119eccb1ae0074e5b3aaccbb74eeRob Landley *
5f91b7c89bc852868692b9518185421ebb52d67b3Rob Landley * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/dmesg.html
62896480c4918f2accccb8301bec457a7bff7377eRob Landley
76a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley// We care that FLAG_c is 1, so keep c at the end.
8fcd2729305888d0d8e4af2e6d158b9bbb97541afRob LandleyUSE_DMESG(NEWTOY(dmesg, "trs#<1n#c[!tr]", TOYFLAG_BIN))
955928b1e0a08d84a5cbc50020f0a8c1024f5b6ceRob Landley
102896480c4918f2accccb8301bec457a7bff7377eRob Landleyconfig DMESG
117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  bool "dmesg"
127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  default y
137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  help
14fcd2729305888d0d8e4af2e6d158b9bbb97541afRob Landley    usage: dmesg [-c] [-r|-t] [-n LEVEL] [-s SIZE]
152896480c4918f2accccb8301bec457a7bff7377eRob Landley
167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    Print or control the kernel ring buffer.
172896480c4918f2accccb8301bec457a7bff7377eRob Landley
186a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    -c	Clear the ring buffer after printing
196a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    -n	Set kernel logging LEVEL (1-9)
206a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    -r	Raw output (with <level markers>)
216a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    -s	Show the last SIZE many bytes
2238a5493031bca46263038964a8f5b188d7e9304eMark Salyzyn    -t	Don't print kernel's timestamps
232896480c4918f2accccb8301bec457a7bff7377eRob Landley*/
24b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley
25c0e56edaf256adb6c60c5a052525a1ffbb927901Rob Landley#define FOR_dmesg
26b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley#include "toys.h"
27b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley#include <sys/klog.h>
28b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley
29c0e56edaf256adb6c60c5a052525a1ffbb927901Rob LandleyGLOBALS(
307aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  long level;
317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  long size;
32b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley)
33b1aaba1fc8176ac0b7c202a664d2554aa0967116Rob Landley
34efda21ca931766eed6cfc49d1b2122c53827d9fcRob Landleyvoid dmesg_main(void)
35b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley{
367aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  // For -n just tell kernel to which messages to keep.
376a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley  if (toys.optflags & FLAG_n) {
386a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    if (klogctl(8, NULL, TT.level)) perror_exit("klogctl");
397aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  } else {
406a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    char *data, *to, *from;
416a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    int size;
427aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
437aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    // Figure out how much data we need, and fetch it.
447aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    size = TT.size;
456a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    if (!size && 1>(size = klogctl(10, 0, 0))) perror_exit("klogctl");;
466a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    data = to = from = xmalloc(size+1);
476a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    size = klogctl(3 + (toys.optflags & FLAG_c), data, size);
48abb5ae390342acf8eea2903033fb1d5879845b43Elliott Hughes    if (size < 0) perror_exit("klogctl");
496a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    data[size] = 0;
507aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley
5138a5493031bca46263038964a8f5b188d7e9304eMark Salyzyn    // Filter out level markers and optionally time markers
526a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    if (!(toys.optflags & FLAG_r)) while ((from - data) < size) {
5338a5493031bca46263038964a8f5b188d7e9304eMark Salyzyn      if (from == data || from[-1] == '\n') {
54fcd2729305888d0d8e4af2e6d158b9bbb97541afRob Landley        char *to;
556a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley
56fcd2729305888d0d8e4af2e6d158b9bbb97541afRob Landley        if (*from == '<' && (to = strchr(from, '>'))) from = ++to;
57fcd2729305888d0d8e4af2e6d158b9bbb97541afRob Landley        if ((toys.optflags&FLAG_t) && *from == '[' && (to = strchr(from, ']')))
58fcd2729305888d0d8e4af2e6d158b9bbb97541afRob Landley          from = to+1+(to[1]==' ');
596a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley      }
606a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley      *(to++) = *(from++);
616a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    } else to = data+size;
626a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley
636a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    // Write result. The odds of somebody requesting a buffer of size 3 and
646a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    // getting "<1>" are remote, but don't segfault if they do.
656a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley    if (to != data) {
666a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley      xwrite(1, data, to-data);
676a66049f5038f4d1e5bdb2cdcb5609a5c4184c90Rob Landley      if (to[-1] != '\n') xputc('\n');
687aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    }
697aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley    if (CFG_TOYBOX_FREE) free(data);
707aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley  }
71b5b82d92d26934b3d49adb146e8a4bd542ab8dfbRob Landley}
72