From 5e906443353216813bafe9c8f04150889775eace Mon Sep 17 00:00:00 2001 From: Mike Lowis Date: Thu, 28 Apr 2016 12:44:13 -0400 Subject: [PATCH] Added initial implementation of dmesg --- Makefile | 5 +- include/util.h | 60 ++++++++++++++--------- source/dmesg.c | 126 +++++++++++++++++++++---------------------------- 3 files changed, 95 insertions(+), 96 deletions(-) diff --git a/Makefile b/Makefile index 642dbf78..b0894fc5 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ BUILD = $(CC) $(CFLAGS) -o $@ $< #------------------------------------------------------------------------------ # Build-Specific Macros #------------------------------------------------------------------------------ -BINS = init getty login +BINS = init getty login dmesg # load user-specific settings -include config.mk @@ -36,6 +36,9 @@ getty: source/getty.c login: source/login.c $(BUILD) -lcrypt +dmesg: source/dmesg.c + $(BUILD) + clean: $(RM) $(BINS) diff --git a/include/util.h b/include/util.h index 95b4afa3..824991ef 100644 --- a/include/util.h +++ b/include/util.h @@ -31,6 +31,28 @@ typedef signed char schar; typedef long long vlong; typedef unsigned long long uvlong; +/* Error Handling Macros + *****************************************************************************/ +#ifdef NDEBUG + #define debug(msg, ...) \ + ((void)0) +#else + #define debug(msg, ...) \ + fprintf(stderr, "DEBUG %s:%d: " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#endif + +#define errnostr() \ + (errno == 0 ? "None" : strerror(errno)) + +#define print_error(msg, ...) \ + fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " msg "\n", __FILE__, __LINE__, errnostr(), ##__VA_ARGS__) + +#define check(expr, msg, ...) \ + if(!(expr)) { print_error(msg, ##__VA_ARGS__); errno=0; goto error; } + +#define sentinel(msg, ...) \ + { print_error(msg, ##__VA_ARGS__); errno=0; goto error; } + /* Generic Death Function *****************************************************************************/ static void die(const char* msgfmt, ...) @@ -163,6 +185,22 @@ static char* estrdup(const char *s) return ns; } +static long int estrtol(const char* str, int base) { + errno = 0; + long int result = strtol(str, NULL, base); + if (errno) + die("estrtol failed: %s", errnostr()); + return result; +} + +static unsigned long int estrtoul(const char* str, int base) { + errno = 0; + unsigned long int result = strtol(str, NULL, base); + if (errno) + die("estrtoul failed: %s", errnostr()); + return result; +} + /* Option Parsing ****************************************************************************** * This following macros implement a simple POSIX-style option parsing strategy. @@ -262,28 +300,6 @@ static inline char* _getopt_(int* p_argc, char*** p_argv) { #define OPTLONG \ case '-' -/* Error Handling - *****************************************************************************/ -#ifdef NDEBUG - #define debug(msg, ...) \ - ((void)0) -#else - #define debug(msg, ...) \ - fprintf(stderr, "DEBUG %s:%d: " msg "\n", __FILE__, __LINE__, ##__VA_ARGS__) -#endif - -#define errnostr() \ - (errno == 0 ? "None" : strerror(errno)) - -#define print_error(msg, ...) \ - fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " msg "\n", __FILE__, __LINE__, errnostr(), ##__VA_ARGS__) - -#define check(expr, msg, ...) \ - if(!(expr)) { print_error(msg, ##__VA_ARGS__); errno=0; goto error; } - -#define sentinel(msg, ...) \ - { print_error(msg, ##__VA_ARGS__); errno=0; goto error; } - /* Miscellaneous *****************************************************************************/ #ifndef nelem diff --git a/source/dmesg.c b/source/dmesg.c index fff14615..20f23ec8 100644 --- a/source/dmesg.c +++ b/source/dmesg.c @@ -1,81 +1,61 @@ -/* See LICENSE file for copyright and license details. */ -#include - -#include -#include -#include -#include - +/** + @brief + @author Michael D. Lowis + @license BSD 2-clause License +*/ #include "util.h" +#include -enum { - SYSLOG_ACTION_READ_ALL = 3, - SYSLOG_ACTION_CLEAR = 5, - SYSLOG_ACTION_CONSOLE_LEVEL = 8, - SYSLOG_ACTION_SIZE_BUFFER = 10 -}; +#define SYSLOG_ACTION_READ_ALL 3 +#define SYSLOG_ACTION_CLEAR 5 +#define SYSLOG_ACTION_CONSOLE_LEVEL 8 +#define SYSLOG_ACTION_SIZE_BUFFER 10 -static void -dmesg_show(const void *buf, size_t n) -{ - const char *p = buf; - ssize_t r; +char* ARGV0; - r = write(1, p, n); - if (r < 0) - eprintf("write:"); - if (r > 0 && p[r - 1] != '\n') - putchar('\n'); +static void usage(void) { + fprintf(stderr, "Usage: %s [-Cc] [-n level]\n", ARGV0); + exit(1); } -static void -usage(void) -{ - eprintf("usage: %s [-Ccr] [-n level]\n", argv0); +int eklogctl(int type, char *bufp, int len) { + int nbytes = klogctl(type, bufp, len); + if (nbytes < 0) + die("klogctl failed: %s", errnostr()); + return nbytes; } -int -main(int argc, char *argv[]) -{ - int n; - char *buf; - int cflag = 0; - long level; - - ARGBEGIN { - case 'C': - if (klogctl(SYSLOG_ACTION_CLEAR, NULL, 0) < 0) - eprintf("klogctl:"); - return 0; - case 'c': - cflag = 1; - break; - case 'r': - break; - case 'n': - level = estrtol(EARGF(usage()), 10); - if (klogctl(SYSLOG_ACTION_CONSOLE_LEVEL, NULL, level) < 0) - eprintf("klogctl:"); - return 0; - default: - usage(); - } ARGEND; - - n = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); - if (n < 0) - eprintf("klogctl:"); - - buf = emalloc(n); - - n = klogctl(SYSLOG_ACTION_READ_ALL, buf, n); - if (n < 0) - eprintf("klogctl:"); - - dmesg_show(buf, n); - - if (cflag && klogctl(SYSLOG_ACTION_CLEAR, NULL, 0) < 0) - eprintf("klogctl:"); - - free(buf); - return 0; -} \ No newline at end of file +int main(int argc, char** argv) { + long level = -1; + bool read = true; + bool clear_before = false; + bool clear_after = false; + /* Parse command line options */ + OPTBEGIN { + case 'C': clear_before = true; read = false; break; + case 'c': clear_after = true; read = true; break; + case 'n': level = estrtol(EOPTARG(usage()), 10); break; + default: + usage(); + } OPTEND; + /* clear the before before doing anything else */ + if (clear_before) + eklogctl(SYSLOG_ACTION_CLEAR, NULL, 0); + /* Set the log level */ + if (level >= 0) + eklogctl(SYSLOG_ACTION_CONSOLE_LEVEL, NULL, level); + /* Read the raw log data and print it out */ + if (read) { + int nbytes = eklogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); + char* buf = (char*)emalloc(nbytes); + eklogctl(SYSLOG_ACTION_READ_ALL, buf, nbytes); + nbytes = efwrite(buf, 1, nbytes, stdout); + if (buf[nbytes - 1] != '\n') + fputc('\n', stdout); + free(buf); + } + /* Clear the log after we've read it out */ + if (clear_after) + eklogctl(SYSLOG_ACTION_CLEAR, NULL, 0); + return 0; +} -- 2.52.0