busybox/util-linux/dmesg.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 *
   4 * dmesg - display/control kernel ring buffer.
   5 *
   6 * Copyright 2006 Rob Landley <rob@landley.net>
   7 * Copyright 2006 Bernhard Reutner-Fischer <rep.nop@aon.at>
   8 *
   9 * Licensed under GPLv2, see file LICENSE in this source tree.
  10 */
  11//config:config DMESG
  12//config:       bool "dmesg (3.7 kb)"
  13//config:       default y
  14//config:       select PLATFORM_LINUX
  15//config:       help
  16//config:       dmesg is used to examine or control the kernel ring buffer. When the
  17//config:       Linux kernel prints messages to the system log, they are stored in
  18//config:       the kernel ring buffer. You can use dmesg to print the kernel's ring
  19//config:       buffer, clear the kernel ring buffer, change the size of the kernel
  20//config:       ring buffer, and change the priority level at which kernel messages
  21//config:       are also logged to the system console. Enable this option if you
  22//config:       wish to enable the 'dmesg' utility.
  23//config:
  24//config:config FEATURE_DMESG_PRETTY
  25//config:       bool "Pretty output"
  26//config:       default y
  27//config:       depends on DMESG
  28//config:       help
  29//config:       If you wish to scrub the syslog level from the output, say 'Y' here.
  30//config:       The syslog level is a string prefixed to every line with the form
  31//config:       "<#>".
  32//config:
  33//config:       With this option you will see:
  34//config:               # dmesg
  35//config:               Linux version 2.6.17.4 .....
  36//config:               BIOS-provided physical RAM map:
  37//config:                BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
  38//config:
  39//config:       Without this option you will see:
  40//config:               # dmesg
  41//config:               <5>Linux version 2.6.17.4 .....
  42//config:               <6>BIOS-provided physical RAM map:
  43//config:               <6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
  44
  45//applet:IF_DMESG(APPLET(dmesg, BB_DIR_BIN, BB_SUID_DROP))
  46
  47//kbuild:lib-$(CONFIG_DMESG) += dmesg.o
  48
  49//usage:#define dmesg_trivial_usage
  50//usage:       "[-c] [-n LEVEL] [-s SIZE]"
  51//usage:#define dmesg_full_usage "\n\n"
  52//usage:       "Print or control the kernel ring buffer\n"
  53//usage:     "\n        -c              Clear ring buffer after printing"
  54//usage:     "\n        -n LEVEL        Set console logging level"
  55//usage:     "\n        -s SIZE         Buffer size"
  56//usage:     "\n        -r              Print raw message buffer"
  57
  58#include <sys/klog.h>
  59#include "libbb.h"
  60
  61int dmesg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  62int dmesg_main(int argc UNUSED_PARAM, char **argv)
  63{
  64        int len, level;
  65        char *buf;
  66        unsigned opts;
  67        enum {
  68                OPT_c = 1 << 0,
  69                OPT_s = 1 << 1,
  70                OPT_n = 1 << 2,
  71                OPT_r = 1 << 3
  72        };
  73
  74        opts = getopt32(argv, "cs:+n:+r", &len, &level);
  75        if (opts & OPT_n) {
  76                if (klogctl(8, NULL, (long) level))
  77                        bb_perror_msg_and_die("klogctl");
  78                return EXIT_SUCCESS;
  79        }
  80
  81        if (!(opts & OPT_s))
  82                len = klogctl(10, NULL, 0); /* read ring buffer size */
  83        if (len < 16*1024)
  84                len = 16*1024;
  85        if (len > 16*1024*1024)
  86                len = 16*1024*1024;
  87
  88        buf = xmalloc(len);
  89        len = klogctl(3 + (opts & OPT_c), buf, len); /* read ring buffer */
  90        if (len < 0)
  91                bb_perror_msg_and_die("klogctl");
  92        if (len == 0)
  93                return EXIT_SUCCESS;
  94
  95
  96        if (ENABLE_FEATURE_DMESG_PRETTY && !(opts & OPT_r)) {
  97                int last = '\n';
  98                int in = 0;
  99
 100                /* Skip <[0-9]+> at the start of lines */
 101                while (1) {
 102                        if (last == '\n' && buf[in] == '<') {
 103                                while (buf[in++] != '>' && in < len)
 104                                        ;
 105                        } else {
 106                                last = buf[in++];
 107                                putchar(last);
 108                        }
 109                        if (in >= len)
 110                                break;
 111                }
 112                /* Make sure we end with a newline */
 113                if (last != '\n')
 114                        bb_putchar('\n');
 115        } else {
 116                full_write(STDOUT_FILENO, buf, len);
 117                if (buf[len-1] != '\n')
 118                        bb_putchar('\n');
 119        }
 120
 121        if (ENABLE_FEATURE_CLEAN_UP) free(buf);
 122
 123        return EXIT_SUCCESS;
 124}
 125