aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Łyszczek <michal.lyszczek@bofc.pl>2018-04-17 23:10:11 +0200
committerMichał Łyszczek <michal.lyszczek@bofc.pl>2018-04-17 23:10:11 +0200
commit021965eedc03dd17b98d56f2bb45cac9b391b7a2 (patch)
tree803806fbdd844bc1c7a17162a323ae3f39a12247
parenta34a7315472f825df64d553b69f30693a38a955e (diff)
downloadembedlog-021965eedc03dd17b98d56f2bb45cac9b391b7a2.tar.gz
embedlog-021965eedc03dd17b98d56f2bb45cac9b391b7a2.tar.bz2
embedlog-021965eedc03dd17b98d56f2bb45cac9b391b7a2.zip
add: logging of binary data
-rw-r--r--configure.ac19
-rw-r--r--embedlog-sources.mk7
-rw-r--r--include/embedlog.h6
-rw-r--r--man/el_print.3119
-rw-r--r--src/el-decode-number.c86
-rw-r--r--src/el-encode-number.c112
-rw-r--r--src/el-file.c54
-rw-r--r--src/el-file.h15
-rw-r--r--src/el-options.c11
-rw-r--r--src/el-options.h18
-rw-r--r--src/el-pbinary.c223
-rw-r--r--src/el-perror.c3
-rw-r--r--src/el-pmemory.c5
-rw-r--r--src/el-print.c209
-rw-r--r--src/el-private.h (renamed from src/config-priv.h)92
-rw-r--r--src/el-puts.c77
-rw-r--r--src/el-syslog.c9
-rw-r--r--src/el-ts.c249
-rw-r--r--src/el-tty.c4
-rw-r--r--src/el-tty.h16
-rw-r--r--tst/Makefile.am1
l---------tst/el-decode-number.c1
l---------tst/el-encode-number.c1
l---------tst/el-pbinary.c1
l---------tst/el-ts.c1
-rw-r--r--tst/main.c2
-rw-r--r--tst/test-el-file.c21
-rw-r--r--tst/test-el-options.c3
-rw-r--r--tst/test-el-pbinary.c670
-rw-r--r--tst/test-el-print.c3
-rw-r--r--tst/test-group-list.h1
31 files changed, 1703 insertions, 336 deletions
diff --git a/configure.ac b/configure.ac
index 74694a4..30b7149 100644
--- a/configure.ac
+++ b/configure.ac
@@ -223,6 +223,24 @@ AS_IF([test "x$enable_clock" = "xyes"],
###
+# --enable-binary
+#
+
+
+AC_ARG_ENABLE([binary-logs],
+ AS_HELP_STRING([--enable-binary-logs], [Enable printing binary logs]),
+ [], [enable_binary_logs="no"])
+
+AM_CONDITIONAL([ENABLE_BINARY_LOGS], [test "x$enable_binary_logs" = "xyes"])
+AS_IF([test "x$enable_binary_logs" = "xyes"],
+[
+ AC_DEFINE([ENABLE_PREFIX], [1], [Enable printing binary logs])
+ AC_CHECK_FUNCS([memcpy],,
+ AC_MSG_ERROR(not found, needed by --enable-binary-logs))
+])
+
+
+###
# --enable-prefix
#
@@ -387,6 +405,7 @@ echo "clock() timestamp........... : $enable_clock"
echo "print prefix with each msg.. : $enable_prefix"
echo "print file info with log.... : $enable_finfo"
echo "force portable snprintf......: $enable_portable_snprintf"
+echo "binary logs..................: $enable_binary_logs"
echo "colorize output............. : $enable_colors"
echo "extended colors............. : $enable_colors_extended"
echo "reentrant functions......... : $enable_reentrant"
diff --git a/embedlog-sources.mk b/embedlog-sources.mk
index eb779c0..591111e 100644
--- a/embedlog-sources.mk
+++ b/embedlog-sources.mk
@@ -3,6 +3,9 @@ embedlog_sources = el-options.c \
el-pmemory.c \
el-print.c \
el-puts.c \
+ el-ts.c \
+ el-decode-number.c \
+ el-encode-number.c \
snprintf.c
if ENABLE_OUT_FILE
@@ -12,3 +15,7 @@ endif
if ENABLE_OUT_TTY
embedlog_sources += el-tty.c
endif
+
+if ENABLE_BINARY_LOGS
+embedlog_sources += el-pbinary.c
+endif
diff --git a/include/embedlog.h b/include/embedlog.h
index 29cbba8..ad69196 100644
--- a/include/embedlog.h
+++ b/include/embedlog.h
@@ -170,7 +170,8 @@ int el_pmemory(const char *file, size_t line, enum el_level level,
const void *memory, size_t mlen);
int el_perror(const char *file, size_t line, enum el_level level,
const char *fmt, ...);
-
+int el_putb(const void *memory, size_t mlen);
+int el_pbinary(enum el_level level, const void *memory, size_t mlen);
int el_oinit(struct el_options *options);
int el_ocleanup(struct el_options *options);
@@ -184,6 +185,9 @@ int el_opmemory(const char *file, size_t line, enum el_level level,
struct el_options *options, const void *memory, size_t mlen);
int el_operror(const char *file, size_t line, enum el_level level,
struct el_options *options, const char *fmt, ...);
+int el_oputb(struct el_options *options, const void *memory, size_t mlen);
+int el_opbinary(enum el_level level, struct el_options *options,
+ const void *memory, size_t mlen);
#ifdef __cplusplus
}
diff --git a/man/el_print.3 b/man/el_print.3
index e2d3a22..d15f696 100644
--- a/man/el_print.3
+++ b/man/el_print.3
@@ -13,6 +13,8 @@
.PP
.BI "int el_puts(const char *" message ")"
.br
+.BI "int el_putb(const void *" memory ", size_t " mlen ")"
+.br
.BI "int el_print(const char *" file ", size_t " line ", \
enum el_level " level ", const char *" fmt ", " ... ")"
.br
@@ -24,9 +26,15 @@ enum el_level " level ", const char *" fmt ", " ... ")"
.br
.BI "int el_pmemory(const char *" file ", size_t " line ", \
enum el_level " level ", const void *" memory ", size_t " mlen ")
+.br
+.BI "int el_pbinary(enum el_level " level ", const void *" memory", \
+size_t " mlen ")
.PP
.BI "int el_oputs(struct el_options *" options ", const char *" message ")"
.br
+.BI "int el_putb(struct el_options *" options ", const void *" memory ", \
+size_t " mlen ")"
+.br
.BI "int el_oprint(const char *" file ", size_t " line ", \
enum el_level " level ", struct el_options *" options ", \
const char *" fmt ", " ... ")"
@@ -42,6 +50,9 @@ const char *" fmt ", " ... ")"
.BI "int el_pmemory(const char *" file ", size_t " line ", \
enum el_level " level ", struct el_options *" options ", \
const void *" memory ", size_t " mlen ")"
+.br
+.BI "int el_pbinary(enum el_level " level ", struct el_options *" options ", \
+const void *" memory ", size_t " mlen ")"
.PP
.BI "#define ELF " __FILE__ ", " __LINE__ ", " EL_FATAL
.br
@@ -70,7 +81,7 @@ __ISOC99_SOURCE
.SH DESCRIPTION
.PP
Functions print log into configured outputs.
-
+.PP
.BR el_puts (3)
function prints
.I message
@@ -81,6 +92,23 @@ log nor timestamp is printed - even if they are enabled.
Logs printed with this functions are not filtered by log level, and will always
be printed. Prints can still be suppressed by disabling output.
.PP
+.BR el_putb (3)
+function works same as
+.BR el_puts (3)
+but binary data can be passed.
+That binary data will not be printed in ASCII like it it with
+.BR el_pmemory (3).
+If
+.I memory
+contains
+.B NULL
+characters, they will be stored to file.
+If
+.I memory
+is for example
+.B char buf[] = { 0xb0, 0xfc, 0x13, 0x37 }
+then exactly these bytes will be stored into file.
+.PP
.BR el_print (3)
function behaves similar to standard
.BR printf ()
@@ -153,6 +181,95 @@ values.
------ ----------------------------------------------- ----------------
.EE
.PP
+.BR el_pbinary (3)
+is used to log binary data into block device.
+Both metadata and data itself are treated as binary data.
+Such files cannot be read with text tools like
+.BR less ,
+but rather needs special program that will parse the file.
+This may be usefull when you need, for example to log every message on CAN bus.
+If there are a lot of messages, it may be better to store them in binary format
+as this may save *a lot* of space.
+.PP
+.BR el_pbinary (3)
+uses specific format to store metadata to save as much space as possible.
+All numerical values in metadata are variadic in size. Order of fields are as
+follows:
+.PP
+.EX
+ +-------+------------+--------------+-------------+------+
+ | flags | ts_seconds | ts_fractions | data_length | data |
+ +-------+------------+--------------+-------------+------+
+.EE
+.PP
+The only mandatory fields are
+.BR flags ", " data_length " and " data .
+.B flags
+determin what fields are present.
+.B flags
+field is always 1 byte in size and its format is
+.PP
+.EX
+ +------+-------+-----------------------------------------------------------+
+ | bits | value | description |
+ +------+-------+-----------------------------------------------------------+
+ | 0 | 0 | both ts_seconds and ts_fraction will not appear |
+ | +-------+-----------------------------------------------------------+
+ | | 1 | at least ts_seconds will appear, ts_fraction appearance |
+ | | | depends on 1..2 bits values |
+ +------+-------+-----------------------------------------------------------+
+ | 1..2 | 0 | ts_fractions will not appear |
+ | +-------+-----------------------------------------------------------+
+ | | 1 | ts_fractions will hold milliseconds value |
+ | +-------+-----------------------------------------------------------+
+ | | 2 | ts_fractions will hold microseconds value |
+ | +-------+-----------------------------------------------------------+
+ | | 3 | ts_fractions will hold nanoseconds value |
+ +------+-------+-----------------------------------------------------------+
+ | 3..5 | 0..7 | severity of the log, 0 is the highest and 7 is the lowest |
+ +------+-------+-----------------------------------------------------------+
+ | 6..7 | 0..3 | reserved |
+ +------+-------+-----------------------------------------------------------+
+.EE
+.PP
+.BR ts_seconds ", " ts_fractions " and " data_length
+are numerical values with dynamic size.
+Each byte of a numerical value can hold number up to 127 and oldest bit is used
+as continuation bit, if that bit is set, program should treat next byte as next
+part of the same numerical value.
+Below is table with example decimal values and it's encoded counterpart.
+.PP
+.EX
+ +---------------+--------------------------+
+ | decimal value | encoded hex value |
+ +---------------+--------------------------+
+ | 0 | 0x00 |
+ | 1 | 0x01 |
+ | 2 | 0x02 |
+ | 127 | 0x7f |
+ | 128 | 0x80 0x81 |
+ | 129 | 0x81 0x01 |
+ | 255 | 0xff 0x01 |
+ | 256 | 0x80 0x02 |
+ | 257 | 0x81 0x02 |
+ | 16383 | 0xff 0x7f |
+ | 16384 | 0x80 0x80 0x01 |
+ | 16385 | 0x81 0x80 0x01 |
+ | 438478374 | 0xa6 0xcc 0x8a 0xd1 0x01 |
+ | 2147483647 | 0xff 0xff 0xff 0xff 0x07 |
+ | 4294967295 | 0xff 0xff 0xff 0xff 0x0f |
+ +---------------+--------------------------+
+.EE
+.PP
+Encoded number are always
+.BR little-endian ,
+that is first byte is always the least significant byte.
+.PP
+.B data
+is be whatever you want of any size.
+.BR el_pbinary (3)
+uses only timestamp and log level, rest of the options are simply ignores.
+.PP
.BR el_print (3),
.BR el_vprint (3),
.BR el_perror (3)
diff --git a/src/el-decode-number.c b/src/el-decode-number.c
new file mode 100644
index 0000000..5a8be82
--- /dev/null
+++ b/src/el-decode-number.c
@@ -0,0 +1,86 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ==========================================================================
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
+
+ ========================================================================== */
+
+
+#include <limits.h>
+
+#include "el-private.h"
+
+
+/* ==========================================================================
+ __ __ _
+ ____ __ __ / /_ / /(_)_____
+ / __ \ / / / // __ \ / // // ___/
+ / /_/ // /_/ // /_/ // // // /__
+ / .___/ \__,_//_.___//_//_/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ Decodes encoded 'number' and stores value into 'out'. Check description
+ of el_encode_number for more information.
+
+ returns number of bytes processed from 'number'
+ ========================================================================== */
+
+
+size_t el_decode_number
+(
+ const void *number, /* number to decode */
+#ifdef LLONG_MAX
+ unsigned long long *out /* decoded number */
+#else
+ unsigned long *out /* decoded number */
+#endif
+)
+{
+ const unsigned char *n; /* just a 'number' as unsigned cahr */
+ size_t i; /* temporary index */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ i = 0;
+ *out = 0;
+ n = number;
+
+ do
+ {
+ /*
+ * multiple stuff is happening in this one-liner
+ *
+ * - first we take 7 bits of number
+ * - calculate weigth of current number
+ * - set current number into right position of out
+ */
+
+ *out |= (n[i] & 0x7f) << (i * 7);
+
+ /*
+ * we do this until number lacks of continuation bit, which means
+ * we are done
+ */
+ }
+ while (n[i++] & 0x80);
+
+ /*
+ * return number of bytes processed from 'number'
+ */
+
+ return i;
+}
diff --git a/src/el-encode-number.c b/src/el-encode-number.c
new file mode 100644
index 0000000..82a81ac
--- /dev/null
+++ b/src/el-encode-number.c
@@ -0,0 +1,112 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ==========================================================================
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
+
+ ========================================================================== */
+
+
+#include <limits.h>
+
+#include "el-private.h"
+
+
+/* ==========================================================================
+ __ __ _
+ ____ __ __ / /_ / /(_)_____
+ / __ \ / / / // __ \ / // // ___/
+ / /_/ // /_/ // /_/ // // // /__
+ / .___/ \__,_//_.___//_//_/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ This will code 'number' to into as small buffer as possible. Each byte
+ of encoded value can hold 7 bits of data and 1 bit (oldest) of
+ continuation information. If continuation bit is set, that means next
+ byte contains next 7bit of number information. This allows us to store
+ value up to 127 in one byte and values up to 16383 in two bytes and so
+ on. 'out' must be long enough to hold enough encoded bytes or undefined
+ behaviour will occur.
+
+ returns number of bytes stored into 'out' buffer.
+ ========================================================================== */
+
+
+size_t el_encode_number
+(
+#ifdef LLONG_MAX
+ unsigned long long number, /* value to encode */
+#else
+ unsigned long number, /* value to encode */
+#endif
+ void *out /* memory where encoded value will be set */
+)
+{
+ unsigned char *o; /* just 'out' as unsigned char */
+ size_t n; /* number of bytes stored in 'out' */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ o = out;
+ n = 0;
+
+ do
+ {
+ /*
+ * put only youngest 7 bits into out - that's a max number single
+ * byte can hold
+ */
+
+ o[n] = number & 0x7f;
+
+ /*
+ * remove those 7 bits from number, they are used and no longer
+ * needed
+ */
+
+ number >>= 7;
+
+ /*
+ * if we didn't process whole number, set oldest bit to 1, this is
+ * continuation bit, it will tell decoder that next bytes will hold
+ * next 7bits of number
+ */
+
+ if (number)
+ {
+ o[n] |= 0x80;
+ }
+
+ /*
+ * increment n to indicate we store a byte in 'out' buffer
+ */
+
+ ++n;
+
+ /*
+ * do this until there is anyting else left in number
+ */
+ }
+ while (number);
+
+ /*
+ * after job's done, return number of bytes stored in 'out'
+ */
+
+ return n;
+}
+
+
+
diff --git a/src/el-file.c b/src/el-file.c
index 80bb3bd..8c051e7 100644
--- a/src/el-file.c
+++ b/src/el-file.c
@@ -42,7 +42,7 @@
# include "config.h"
#endif
-#include "el-options.h"
+#include "el-private.h"
#if HAVE_UNISTD_H
# include <unistd.h>
@@ -545,16 +545,14 @@ int el_file_open
========================================================================== */
-int el_file_puts
+int el_file_putb
(
- struct el_options *options, /* printing options */
- const char *s /* string to 'put' into file */
+ struct el_options *options, /* printing options */
+ const void *mem, /* memory to 'put' into file */
+ size_t mlen /* size of buffer 'mlen' */
+
)
{
- int sl; /* size of the s message */
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
if (options->current_log && options->current_log[0] == '\0')
{
/*
@@ -565,11 +563,9 @@ int el_file_puts
return -1;
}
- sl = strlen(s);
-
if (options->frotate_number)
{
- if (options->fpos != 0 && options->fpos + sl > options->frotate_size)
+ if (options->fpos != 0 && options->fpos + mlen > options->frotate_size)
{
/*
* we get here only when frotate is enabled, and writing to
@@ -585,7 +581,7 @@ int el_file_puts
}
}
- if (sl > options->frotate_size)
+ if (mlen > options->frotate_size)
{
/*
* we can't fit message even in an empty file, in such case we
@@ -593,7 +589,7 @@ int el_file_puts
* configured frotate_size
*/
- sl = options->frotate_size;
+ mlen = options->frotate_size;
}
}
@@ -622,13 +618,13 @@ int el_file_puts
options->fpos = 0;
}
- if (fwrite(s, sl, 1, options->file) != 1)
+ if (fwrite(mem, mlen, 1, options->file) != 1)
{
return -1;
}
- options->fpos += sl;
- options->written_after_sync += sl;
+ options->fpos += mlen;
+ options->written_after_sync += mlen;
if (options->written_after_sync >= options->file_sync_every ||
options->level_current_msg <= options->file_sync_level)
@@ -647,7 +643,7 @@ int el_file_puts
* sync our file and metadata, parent directory might not get
* flushed and there will not be entry for our file - meaning file
* will be lost too, but such situations are ultra rare and there
- * isn't really much we can do about it here but prying.
+ * isn't really much we can do about it here but praying.
*/
#if HAVE_FSYNC && HAVE_FILENO
@@ -681,7 +677,7 @@ int el_file_puts
#else /* HAVE_FSYNC && HAVE_FILENO */
/*
* if system does not implement fileno and fsync our only hope lies
- * int closing (which should sync file to block device) and then
+ * in closing (which should sync file to block device) and then
* opening file again. Yup, performance will suck, but hey, its
* about data safety!
*/
@@ -693,11 +689,11 @@ int el_file_puts
errno = EBADF;
return -1;
}
+#endif /* HAVE_FSYNC && HAVE_FILENO */
#ifdef RUN_TESTS
file_synced = 1;
#endif /* RUN_TESTS */
-#endif /* HAVE_FSYNC && HAVE_FILENO */
options->written_after_sync = 0;
}
@@ -707,6 +703,26 @@ int el_file_puts
/* ==========================================================================
+ Puts string 's' into file if needed rotates file
+ ========================================================================== */
+
+
+int el_file_puts
+(
+ struct el_options *options, /* printing options */
+ const char *s /* string to 'put' into file */
+)
+{
+ size_t slen; /* size of string 's' */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ slen = strlen(s);
+ return el_file_putb(options, (unsigned char *)s, slen);
+}
+
+
+/* ==========================================================================
free resources allocated by this module
========================================================================== */
diff --git a/src/el-file.h b/src/el-file.h
deleted file mode 100644
index 42687b6..0000000
--- a/src/el-file.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* ==========================================================================
- Licensed under BSD 2clause license See LICENSE file for more information
- Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
- ========================================================================== */
-
-#ifndef EL_FILE_H
-#define EL_FILE_H 1
-
-#include "el-options.h"
-
-int el_file_open(struct el_options *);
-int el_file_puts(struct el_options *, const char *);
-void el_file_cleanup(struct el_options *);
-
-#endif
diff --git a/src/el-options.c b/src/el-options.c
index a43dd89..a4ba538 100644
--- a/src/el-options.c
+++ b/src/el-options.c
@@ -39,20 +39,11 @@
#include "config.h"
#endif
-#include "el-options.h"
-#include "embedlog.h"
-#include "valid.h"
+#include "el-private.h"
#include <errno.h>
#include <string.h>
-#if ENABLE_OUT_FILE
-#include "el-file.h"
-#endif
-
-#if ENABLE_OUT_TTY
-#include "el-tty.h"
-#endif
/* ==========================================================================
__ __ __
diff --git a/src/el-options.h b/src/el-options.h
deleted file mode 100644
index 3149615..0000000
--- a/src/el-options.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* ==========================================================================
- Licensed under BSD 2clause license. See LICENSE file for more information
- Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
- ========================================================================== */
-
-
-#ifndef EL_OPTIONS_H
-#define EL_OPTIONS_H 1
-
-
-#include "embedlog.h"
-
-
-extern struct el_options g_options;
-
-int el_log_allowed(struct el_options *, enum el_level);
-
-#endif
diff --git a/src/el-pbinary.c b/src/el-pbinary.c
new file mode 100644
index 0000000..a8f967b
--- /dev/null
+++ b/src/el-pbinary.c
@@ -0,0 +1,223 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ==========================================================================
+ -------------------------------------------------------------
+ / Module reponsible for printing binary logs. And by binary I \
+ | don't mean only metadata and logs in ASCII, but full binary |
+ | including data. This may be useful when one need to log ie. |
+ | every message it saw on CAN. It would be a waste of space |
+ | to log it in ASCII when binary data can be less by an order |
+ \ of magnitude /
+ -------------------------------------------------------------
+ \
+ \ , _ ___.--'''`--''//-,-_--_.
+ \`"' ` || \\ \ \\/ / // / ,-\\`,_
+ /'` \ \ || Y | \|/ / // / - |__ `-,
+ /@"\ ` \ `\ | | ||/ // | \/ \ `-._`-,_.,
+ / _.-. `.-\,___/\ _/|_/_\_\/|_/ | `-._._)
+ `-'``/ / | // \__/\__ / \__/ \
+ `-' /-\/ | -| \__ \ |-' |
+ __/\ / _/ \/ __,-' ) ,' _|'
+ (((__/(((_.' ((___..-'((__,'
+ ========================================================================== */
+
+
+/* ==========================================================================
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
+
+ ========================================================================== */
+
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "el-private.h"
+
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+
+
+/* ==========================================================================
+ _ __ __
+ ____ _____ (_)_ __ ____ _ / /_ ___ / /_ __ __ ____ ___ _____
+ / __ \ / ___// /| | / // __ `// __// _ \ / __// / / // __ \ / _ \ / ___/
+ / /_/ // / / / | |/ // /_/ // /_ / __/ / /_ / /_/ // /_/ // __/(__ )
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/ \__/ \__, // .___/ \___//____/
+/_/ /____//_/
+ ========================================================================== */
+
+
+#define FLAG_TS (0x01)
+
+#define FLAG_TS_FRACT_NONE (0x00)
+#define FLAG_TS_FRACT_NSEC (0x01)
+#define FLAG_TS_FRACT_USEC (0x02)
+#define FLAG_TS_FRACT_MSEC (0x03)
+#define FLAG_TS_FRACT_MASK (0x03)
+#define FLAG_TS_FRACT_SHIFT (1)
+
+#define FLAG_LEVEL_MASK (0x07)
+#define FLAG_LEVEL_SHIFT (3)
+
+
+/* ==========================================================================
+ _ __
+ ____ _____ (_)_ __ ____ _ / /_ ___
+ / __ \ / ___// /| | / // __ `// __// _ \
+ / /_/ // / / / | |/ // /_/ // /_ / __/
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ Puts flags with log information to buf. Flags is single byte with fields
+
+ bit 0 timestamp enabled/disabled
+ bit 1-2 fraction timestamp (off, nsec, usec, msec)
+ bit 3-5 severity of the log
+ bit 6-7 reserved
+ ========================================================================== */
+
+
+static size_t el_flags
+(
+ enum el_level level,
+ struct el_options *options,
+ unsigned char *buf
+)
+{
+ *buf = 0;
+
+ if (options->timestamp != EL_TS_OFF)
+ {
+ *buf |= FLAG_TS;
+
+ /*
+ * fraction of seconds can be printed only when timestamp is on
+ */
+
+ if (options->timestamp_useconds)
+ {
+ *buf |= FLAG_TS_FRACT_USEC << FLAG_TS_FRACT_SHIFT;
+ }
+ }
+
+ *buf |= level << FLAG_LEVEL_SHIFT;
+
+ return 1;
+}
+
+
+/* ==========================================================================
+ __ __ _
+ ____ __ __ / /_ / /(_)_____
+ / __ \ / / / // __ \ / // // ___/
+ / /_/ // /_/ // /_/ // // // /__
+ / .___/ \__,_//_.___//_//_/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+int el_opbinary
+(
+ enum el_level level,
+ struct el_options *options,
+ const void *memory,
+ size_t mlen
+)
+{
+ unsigned char buf[EL_BUF_MAX]; /* buffer for message to print */
+ size_t l; /* length of encoded mlen */
+ size_t w; /* bytes written to buf */
+ int e; /* cache for errno */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ VALID(EINVAL, mlen);
+ VALID(EINVAL, memory);
+ VALID(EINVAL, options);
+ VALID(ENODEV, options->outputs);
+ VALID(ERANGE, el_log_allowed(options, level));
+
+ e = 0;
+ w = el_flags(level, options, buf);
+ w += el_timestamp(options, buf + w, TS_BINARY);
+
+ /*
+ * encode mlen to know how much bytes we are going to need
+ */
+
+ l = el_encode_number(mlen, buf + w);
+
+ if (w + l + mlen > sizeof(buf))
+ {
+ /*
+ * user tries to print more that than we can hold in our buffer,
+ * buffer overflow attack? Not going to happen! We truncate it.
+ */
+
+ mlen = EL_BUF_MAX - w - l;
+ e = ENOBUFS;
+ }
+
+ /*
+ * know that we know real value of mlen, we can encode mlen again
+ */
+
+ w += el_encode_number(mlen, buf + w);
+ memcpy(buf + w, memory, mlen);
+ options->level_current_msg = level;
+ w += mlen;
+
+ if (el_oputb(options, buf, w) != 0)
+ {
+ options->level_current_msg = EL_DBG;
+ return -1;
+ }
+
+ options->level_current_msg = EL_DBG;
+
+ if (e)
+ {
+ errno = e;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* ==========================================================================
+ Same as el_opbinary but uses global options object
+ ========================================================================== */
+
+
+int el_pbinary
+(
+ enum el_level level,
+ const void *memory,
+ size_t mlen
+)
+{
+ return el_opbinary(level, &g_options, memory, mlen);
+}
diff --git a/src/el-perror.c b/src/el-perror.c
index 4b7ccb7..b761c08 100644
--- a/src/el-perror.c
+++ b/src/el-perror.c
@@ -28,8 +28,7 @@
#include "config.h"
#endif
-#include "el-options.h"
-#include "embedlog.h"
+#include "el-private.h"
#include <errno.h>
#include <stdarg.h>
diff --git a/src/el-pmemory.c b/src/el-pmemory.c
index c67650a..408086d 100644
--- a/src/el-pmemory.c
+++ b/src/el-pmemory.c
@@ -42,10 +42,7 @@
#include "config.h"
#endif
-#include "config-priv.h"
-#include "el-options.h"
-#include "embedlog.h"
-#include "valid.h"
+#include "el-private.h"
#include <ctype.h>
#include <stdio.h>
diff --git a/src/el-print.c b/src/el-print.c
index c513e3a..6f08c74 100644
--- a/src/el-print.c
+++ b/src/el-print.c
@@ -48,14 +48,7 @@
#include "config.h"
#endif
-#include "config-priv.h"
-#include "el-options.h"
-#include "embedlog.h"
-#include "valid.h"
-
-#if ENABLE_TIMESTAMP
-#include <time.h>
-#endif
+#include "el-private.h"
#include <errno.h>
#include <stdarg.h>
@@ -189,203 +182,6 @@ static size_t el_color
/* ==========================================================================
- returns seconds and microseconds calculated from clock() function
- ========================================================================== */
-
-
-#if ENABLE_TIMESTAMP
-
-#if ENABLE_CLOCK
-
-static void el_ts_clock
-(
- time_t *s, /* seconds will be stored here */
- long *us /* microseconds will be stored here */
-)
-{
- clock_t clk; /* clock value */
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- clk = clock();
-
- *s = clk / CLOCKS_PER_SEC;
- *us = clk % CLOCKS_PER_SEC;
- *us *= 1000000 / CLOCKS_PER_SEC;
-}
-
-#endif /* ENABLE_CLOCK */
-
-/* ==========================================================================
- returns seconds and microseconds calculated from time() function.
- ========================================================================== */
-
-
-static void el_ts_time
-(
- time_t *s, /* seconds will be stored here */
- long *us /* microseconds will be stored here */
-)
-{
- *s = (long)time(NULL);
- *us = 0;
-}
-
-
-/* ==========================================================================
- returns seconds and microseconds calculated from clock_gettime function
- ========================================================================== */
-
-
-#if ENABLE_REALTIME || ENABLE_MONOTONIC
-
-static void el_ts_clock_gettime
-(
- time_t *s, /* seconds will be stored here */
- long *us, /* microseconds will be stored here */
- clockid_t clkid /* clock id */
-)
-{
- struct timespec tp; /* clock value */
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- clock_gettime(clkid, &tp);
-
- *s = tp.tv_sec;
- *us = tp.tv_nsec / 1000;
-}
-
-#endif
-
-#endif /* ENABLE_TIMESTAMP */
-
-
-/* ==========================================================================
- returns current timestamp in 'buf' location. Depending on global
- settings timestamp can be in long or short format. Function will return
- number of bytes copied to 'buf'. If timestamp has been disabled during
- compilation time or in runtime during settings, function will return 0.
- ========================================================================== */
-
-
-static size_t el_timestamp
-(
- struct el_options *options, /* options defining printing style */
- char *buf /* buffer where timestamp will be stored */
-)
-{
-#if ENABLE_TIMESTAMP
- time_t s; /* timestamp seconds */
- long us; /* timestamp microseconds */
- size_t tl; /* timestamp length */
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- if (options->timestamp == EL_TS_OFF)
- {
- /*
- * user doesn't want us to print timestamp, that's fine
- */
-
- return 0;
- }
-
- /*
- * first we get seconds and microseconds from proper timer
- */
-
- switch (options->timestamp_timer)
- {
-#if ENABLE_REALTIME
-
- case EL_TS_TM_REALTIME:
- el_ts_clock_gettime(&s, &us, CLOCK_REALTIME);
- break;
-
-#endif
-
-#if ENABLE_MONOTONIC
-
- case EL_TS_TM_MONOTONIC:
- el_ts_clock_gettime(&s, &us, CLOCK_MONOTONIC);
- break;
-
-#endif
-
- case EL_TS_TM_TIME:
- el_ts_time(&s, &us);
- break;
-
-#if ENABLE_CLOCK
-
- case EL_TS_TM_CLOCK:
- el_ts_clock(&s, &us);
- break;
-
-#endif
-
- default:
- /*
- * bad timer means no timer
- */
-
- return 0;
- }
-
- /*
- * then convert retrieved time into string timestamp
- */
-
- if (options->timestamp == EL_TS_LONG)
- {
- struct tm tm; /* timestamp splitted */
- struct tm *tmp; /* timestamp splitted pointer */
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-# if ENABLE_REENTRANT
- tmp = gmtime_r(&s, &tm);
-# else
- tmp = gmtime(&s);
-# endif
-
- tl = strftime(buf, 21, "[%Y-%m-%d %H:%M:%S", tmp);
- }
- else
- {
-#ifdef LLONG_MAX
- tl = sprintf(buf, "[%lld", (long long)s);
-#else
- /*
- * if long long is not available, code may be suscible to 2038 bug.
- * If you are sure your compiler does support long long type, but
- * doesn't define LLONG_MAX, define this value yourself to enable
- * long long.
- */
- tl = sprintf(buf, "[%ld", (long)s);
-#endif
- }
-
- if (options->timestamp_useconds)
- {
- tl += sprintf(buf + tl, ".%06ld]", us);
- }
- else
- {
- /*
- * if micro seconds are not printed we simply add ending ']'
- */
-
- buf[tl] = ']';
- tl++;
- }
-
- return tl;
-
-#else
- return 0;
-#endif /* ENABLE_TIMESTAMP */
-}
-
-
-/* ==========================================================================
returns pointer to where basename of 's' starts
Examples:
@@ -613,7 +409,7 @@ int el_ovprint
buf[0] = '\0';
w = el_color(options, buf, level);
- w += el_timestamp(options, buf + w);
+ w += el_timestamp(options, buf + w, TS_STRING);
w += el_finfo(options, buf + w, file, num);
if (w != 0 && buf[w - 1] == ']')
@@ -727,3 +523,4 @@ int el_ovprint
return 0;
}
+
diff --git a/src/config-priv.h b/src/el-private.h
index aba78ff..54c4a96 100644
--- a/src/config-priv.h
+++ b/src/el-private.h
@@ -1,12 +1,14 @@
/* ==========================================================================
- Licensed under BSD 2clause license. See LICENSE file for more information
+ Licensed under BSD 2clause license See LICENSE file for more information
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
========================================================================== */
+/*
+ * this file contains stuff internal to the library
+ */
-#ifndef EL_CONFIGPRIV_H
-#define EL_CONFIGPRIV_H 1
-
+#ifndef EL_PRIVATE_H
+#define EL_PRIVATE_H 1
/* ==========================================================================
_ __ __ ____ _ __
@@ -17,20 +19,47 @@
========================================================================== */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "embedlog.h"
+#include "valid.h"
-#if HAVE_CONFIG_H
-#include "config.h"
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
#endif
+#include <limits.h>
-/* ==== library private macros ============================================== */
+/* ==========================================================================
+ __ __ __
+ ____ _ / /____ / /_ ____ _ / / _ __ ____ _ _____ _____
+ / __ `// // __ \ / __ \ / __ `// / | | / // __ `// ___// ___/
+ / /_/ // // /_/ // /_/ // /_/ // / | |/ // /_/ // / (__ )
+ \__, //_/ \____//_.___/ \__,_//_/ |___/ \__,_//_/ /____/
+ /____/
+ ========================================================================== */
-/* ==== defines for el_mprint function ====================================== */
+extern struct el_options g_options;
/* ==========================================================================
- single line of el_print_mem will be similar to this
+ __ __
+ _____ ____ ____ _____ / /_ ____ _ ____ / /_ _____
+ / ___// __ \ / __ \ / ___// __// __ `// __ \ / __// ___/
+ / /__ / /_/ // / / /(__ )/ /_ / /_/ // / / // /_ (__ )
+ \___/ \____//_/ /_//____/ \__/ \__,_//_/ /_/ \__//____/
+
+ ========================================================================== */
+
+
+/* ==== defines for el_pmemory function ===================================== */
+
+
+/* ==========================================================================
+ single line of el_pmemory will be similar to this
0xNNNN HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH HH CCCCCCCCCCCCCCC
========================================================================== */
@@ -182,4 +211,49 @@
#define EL_BUF_MAX (EL_PRE_LEN + (EL_LOG_MAX) + EL_COLORS_LEN)
+/* ==========================================================================
+ Defines if timestamp should be stored into buffer as string or binary
+ ========================================================================== */
+
+
+#define TS_STRING (0)
+#define TS_BINARY (1)
+
+
+/* ==========================================================================
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+#ifdef ENABLE_OUT_FILE
+int el_file_open(struct el_options *options);
+int el_file_puts(struct el_options *options, const char *s);
+int el_file_putb(struct el_options *options, const void *mem, size_t mlen);
+void el_file_cleanup(struct el_options *options);
+#endif
+
+
+#ifdef ENABLE_OUT_TTY
+int el_tty_open(struct el_options *options, const char *dev, speed_t speed);
+int el_tty_puts(struct el_options *options, const char *s);
+int el_tty_close(struct el_options *options);
+#endif
+
+int el_log_allowed(struct el_options *options, enum el_level level);
+size_t el_timestamp(struct el_options *options, char *buf, int binary);
+
+#ifdef LLONG_MAX
+size_t el_encode_number(unsigned long long number, void *out);
+size_t el_decode_number(const void *number, unsigned long long *out);
+#else
+size_t el_encode_number(unsigned long number, void *out);
+size_t el_decode_number(const void *number, unsigned long *out);
+#endif
+
+
#endif
diff --git a/src/el-puts.c b/src/el-puts.c
index 97e90f5..9ba9d1e 100644
--- a/src/el-puts.c
+++ b/src/el-puts.c
@@ -34,20 +34,11 @@
#include "config.h"
#endif
+#include "el-private.h"
+
#include <errno.h>
#include <stdio.h>
-#include "el-options.h"
-#include "embedlog.h"
-#include "valid.h"
-
-#if ENABLE_OUT_FILE
-#include "el-file.h"
-#endif
-
-#if ENABLE_OUT_TTY
-#include "el-tty.h"
-#endif
/* ==========================================================================
__ __ _
@@ -144,3 +135,67 @@ int el_oputs
return rv;
}
+
+
+/* ==========================================================================
+ puts memory 'mem' to all supported output facilities specified by
+ default options. Not all outputs support printing binary data
+ ========================================================================== */
+
+
+int el_putb
+(
+ const void *mem, /* memory location to 'print' */
+ size_t mlen /* size of the mem buffer */
+)
+{
+ return el_oputb(&g_options, mem, mlen);
+}
+
+
+/* ==========================================================================
+ Puts binary data 'mem' of size 'mlen' to enabled output facilities
+ specified by 'options'. No all outputs support printing binary data
+ ========================================================================== */
+
+
+int el_oputb
+(
+ struct el_options *options, /* options defining printing style */
+ const void *mem, /* memory location to 'print' */
+ size_t mlen /* size of the mem buffer */
+)
+{
+ int rv; /* return value from function */
+ int called; /* at least one output was called */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ VALID(EINVAL, options);
+ VALID(EINVAL, mem);
+ VALID(EINVAL, mlen);
+ VALID(ENODEV, options->outputs != 0);
+
+ rv = 0;
+ called = 0;
+
+#if ENABLE_OUT_FILE
+ if (options->outputs & EL_OUT_FILE)
+ {
+ called = 1;
+ rv |= el_file_putb(options, mem, mlen);
+ }
+#endif
+
+ if (called == 0)
+ {
+ /*
+ * couldn't find any supported output for binary logging
+ */
+
+ errno = ENODEV;
+ return -1;
+ }
+
+ return rv;
+}
diff --git a/src/el-syslog.c b/src/el-syslog.c
index c222a40..259beb1 100644
--- a/src/el-syslog.c
+++ b/src/el-syslog.c
@@ -15,12 +15,10 @@
#if HAVE_CONFIG_H
-#include "config.h"
+# include "config.h"
#endif
-#include "el-options.h"
-#include "el-tty.h"
-#include "valid.h"
+#include "el-private.h"
#include <errno.h>
#include <fcntl.h>
@@ -28,9 +26,10 @@
#include <sys/types.h>
#include <unistd.h>
#if HAVE_TERMIOS_H
-#include <termios.h>
+# include <termios.h>
#endif
+
/* ==========================================================================
__ __ _
____ __ __ / /_ / /(_)_____
diff --git a/src/el-ts.c b/src/el-ts.c
new file mode 100644
index 0000000..949a39d
--- /dev/null
+++ b/src/el-ts.c
@@ -0,0 +1,249 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ========================================================================== */
+
+
+/* ==========================================================================
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
+
+ ========================================================================== */
+
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "el-private.h"
+
+#include <time.h>
+
+
+/* ==========================================================================
+ returns seconds and microseconds calculated from clock() function
+ ========================================================================== */
+
+
+#if ENABLE_TIMESTAMP
+#if ENABLE_CLOCK
+static void el_ts_clock
+(
+ time_t *s, /* seconds will be stored here */
+ long *us /* microseconds will be stored here */
+)
+{
+ clock_t clk; /* clock value */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ clk = clock();
+
+ *s = clk / CLOCKS_PER_SEC;
+ *us = clk % CLOCKS_PER_SEC;
+ *us *= 1000000 / CLOCKS_PER_SEC;
+}
+#endif /* ENABLE_CLOCK */
+#endif /* ENABLE_TIMESTAMP */
+
+/* ==========================================================================
+ returns seconds and microseconds calculated from time() function.
+ ========================================================================== */
+
+
+#if ENABLE_TIMESTAMP
+static void el_ts_time
+(
+ time_t *s, /* seconds will be stored here */
+ long *us /* microseconds will be stored here */
+)
+{
+ *s = (long)time(NULL);
+ *us = 0;
+}
+#endif /* ENABLE_TIMESTAMP */
+
+/* ==========================================================================
+ returns seconds and microseconds calculated from clock_gettime function
+ ========================================================================== */
+
+
+#if ENABLE_TIMESTAMP
+#if ENABLE_REALTIME || ENABLE_MONOTONIC
+static void el_ts_clock_gettime
+(
+ time_t *s, /* seconds will be stored here */
+ long *us, /* microseconds will be stored here */
+ clockid_t clkid /* clock id */
+)
+{
+ struct timespec tp; /* clock value */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ clock_gettime(clkid, &tp);
+
+ *s = tp.tv_sec;
+ *us = tp.tv_nsec / 1000;
+}
+#endif /* ENABLE_REALTIME || ENABLE_MONOTONIC */
+#endif /* ENABLE_TIMESTAMP */
+
+
+/* ==========================================================================
+ returns current timestamp in 'buf' location. Depending on global
+ settings timestamp can be in long or short format. Function will return
+ number of bytes copied to 'buf'. If timestamp has been disabled during
+ compilation time or in runtime during settings, function will return 0.
+ ========================================================================== */
+
+
+size_t el_timestamp
+(
+ struct el_options *options, /* options defining printing style */
+ char *buf, /* buffer where timestamp will be stored */
+ int binary /* 1 if timestamp should be binary */
+)
+{
+#if ENABLE_TIMESTAMP
+ time_t s; /* timestamp seconds */
+ long us; /* timestamp microseconds */
+ size_t tl; /* timestamp length */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ if (options->timestamp == EL_TS_OFF)
+ {
+ /*
+ * user doesn't want us to print timestamp, that's fine
+ */
+
+ return 0;
+ }
+
+ /*
+ * first we get seconds and microseconds from proper timer
+ */
+
+ switch (options->timestamp_timer)
+ {
+# if ENABLE_REALTIME
+
+ case EL_TS_TM_REALTIME:
+ el_ts_clock_gettime(&s, &us, CLOCK_REALTIME);
+ break;
+
+# endif
+
+# if ENABLE_MONOTONIC
+
+ case EL_TS_TM_MONOTONIC:
+ el_ts_clock_gettime(&s, &us, CLOCK_MONOTONIC);
+ break;
+
+# endif
+
+ case EL_TS_TM_TIME:
+ el_ts_time(&s, &us);
+ break;
+
+# if ENABLE_CLOCK
+
+ case EL_TS_TM_CLOCK:
+ el_ts_clock(&s, &us);
+ break;
+
+# endif
+
+ default:
+ /*
+ * bad timer means no timer
+ */
+
+ return 0;
+ }
+
+ if (binary)
+ {
+ /*
+ * put encoded seconds timestamp in buf
+ */
+
+# ifdef LLONG_MAX
+ tl = el_encode_number((unsigned long long)s, buf);
+# else
+ tl = el_encode_number((unsigned long)s, buf);
+# endif
+
+ /*
+ * put encoded nano/micro/milli seconds in buf if enabled
+ */
+
+ if (options->timestamp_useconds)
+ {
+# ifdef LLONG_MAX
+ tl += el_encode_number((unsigned long long)us, buf + tl);
+# else
+ tl += el_encode_number((unsigned long)us, buf + tl);
+# endif
+ }
+
+ return tl;
+ }
+ else
+ {
+ /*
+ * then convert retrieved time into string timestamp
+ */
+
+ if (options->timestamp == EL_TS_LONG)
+ {
+ struct tm tm; /* timestamp splitted */
+ struct tm *tmp; /* timestamp splitted pointer */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+# if ENABLE_REENTRANT
+ tmp = gmtime_r(&s, &tm);
+# else
+ tmp = gmtime(&s);
+# endif
+
+ tl = strftime(buf, 21, "[%Y-%m-%d %H:%M:%S", tmp);
+ }
+ else
+ {
+# ifdef LLONG_MAX
+ tl = sprintf(buf, "[%lld", (long long)s);
+# else
+ /*
+ * if long long is not available, code may be suscible to 2038
+ * bug. If you are sure your compiler does support long long
+ * type, but doesn't define LLONG_MAX, define this value to
+ * enable long long.
+ */
+
+ tl = sprintf(buf, "[%ld", (long)s);
+# endif
+ }
+
+ if (options->timestamp_useconds)
+ {
+ tl += sprintf(buf + tl, ".%06ld]", us);
+ }
+ else
+ {
+ /*
+ * if micro seconds are not printed we simply add ending ']'
+ */
+
+ buf[tl] = ']';
+ tl++;
+ }
+
+ return tl;
+ }
+
+#else /* ENABLE_TIMESTAMP */
+ return 0;
+#endif /* ENABLE_TIMESTAMP */
+}
diff --git a/src/el-tty.c b/src/el-tty.c
index c222a40..0b0791d 100644
--- a/src/el-tty.c
+++ b/src/el-tty.c
@@ -18,9 +18,7 @@
#include "config.h"
#endif
-#include "el-options.h"
-#include "el-tty.h"
-#include "valid.h"
+#include "el-private.h"
#include <errno.h>
#include <fcntl.h>
diff --git a/src/el-tty.h b/src/el-tty.h
deleted file mode 100644
index 2d56561..0000000
--- a/src/el-tty.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* ==========================================================================
- Licensed under BSD 2clause license See LICENSE file for more information
- Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
- ========================================================================== */
-
-#ifndef EL_TTY_H
-#define EL_TTY_H 1
-
-#include "el-options.h"
-#include <termios.h>
-
-int el_tty_open(struct el_options *, const char *, speed_t);
-int el_tty_puts(struct el_options *, const char *);
-int el_tty_close(struct el_options *);
-
-#endif
diff --git a/tst/Makefile.am b/tst/Makefile.am
index b07cfbc..1866f7b 100644
--- a/tst/Makefile.am
+++ b/tst/Makefile.am
@@ -9,6 +9,7 @@ test_SOURCES += main.c \
test-el-file.c \
test-el-perror.c \
test-el-pmemory.c \
+ test-el-pbinary.c \
mtest.h \
test-group-list.h
diff --git a/tst/el-decode-number.c b/tst/el-decode-number.c
new file mode 120000
index 0000000..268c6a8
--- /dev/null
+++ b/tst/el-decode-number.c
@@ -0,0 +1 @@
+../src/el-decode-number.c \ No newline at end of file
diff --git a/tst/el-encode-number.c b/tst/el-encode-number.c
new file mode 120000
index 0000000..c90c2c0
--- /dev/null
+++ b/tst/el-encode-number.c
@@ -0,0 +1 @@
+../src/el-encode-number.c \ No newline at end of file
diff --git a/tst/el-pbinary.c b/tst/el-pbinary.c
new file mode 120000
index 0000000..3e46c13
--- /dev/null
+++ b/tst/el-pbinary.c
@@ -0,0 +1 @@
+../src/el-pbinary.c \ No newline at end of file
diff --git a/tst/el-ts.c b/tst/el-ts.c
new file mode 120000
index 0000000..478d0cd
--- /dev/null
+++ b/tst/el-ts.c
@@ -0,0 +1 @@
+../src/el-ts.c \ No newline at end of file
diff --git a/tst/main.c b/tst/main.c
index 2d282f3..8a73d00 100644
--- a/tst/main.c
+++ b/tst/main.c
@@ -3,7 +3,6 @@
Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
========================================================================== */
-#include "embedlog.h"
#include "mtest.h"
#include "test-group-list.h"
@@ -16,5 +15,6 @@ int main(void)
el_file_test_group();
el_perror_test_group();
el_pmemory_test_group();
+ el_pbinary_test_group();
mt_return();
}
diff --git a/tst/test-el-file.c b/tst/test-el-file.c
index 4fa7980..31f0768 100644
--- a/tst/test-el-file.c
+++ b/tst/test-el-file.c
@@ -53,17 +53,11 @@ int file_synced;
/* ==========================================================================
- _ __
- ____ _____ (_)_ __ ____ _ / /_ ___
- / __ \ / ___// /| | / // __ `// __// _ \
- / /_/ // / / / | |/ // /_/ // /_ / __/
- / .___//_/ /_/ |___/ \__,_/ \__/ \___/
- /_/
- _ __ __
- _ __ ____ _ _____ (_)____ _ / /_ / /___ _____
- | | / // __ `// ___// // __ `// __ \ / // _ \ / ___/
- | |/ // /_/ // / / // /_/ // /_/ // // __/(__ )
- |___/ \__,_//_/ /_/ \__,_//_.___//_/ \___//____/
+ __ __
+ _____ ____ ____ _____ / /_ ____ _ ____ / /_ _____
+ / ___// __ \ / __ \ / ___// __// __ `// __ \ / __// ___/
+ / /__ / /_/ // / / /(__ )/ /_ / /_/ // / / // /_ (__ )
+ \___/ \____//_/ /_//____/ \__/ \__,_//_/ /_/ \__//____/
========================================================================== */
@@ -74,6 +68,11 @@ int file_synced;
#define s5 "qwert"
#define s3 "asd"
#define s1 "a"
+static unsigned char d1[] = { 0x01 };
+static unsigned char d2[] = { 0x53, 0x10 };
+static unsigned char d3[] = { 0x00, 0x10, 0x12 };
+static unsigned char d5[] = { 'f', 'o', 'o', 0x00, 'b' };
+static unsigned char d8[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
mt_defs_ext();
diff --git a/tst/test-el-options.c b/tst/test-el-options.c
index be1899b..47c8fee 100644
--- a/tst/test-el-options.c
+++ b/tst/test-el-options.c
@@ -16,8 +16,7 @@
#include <string.h>
#include <errno.h>
-#include "embedlog.h"
-#include "el-options.h"
+#include "el-private.h"
#include "mtest.h"
#include "test-group-list.h"
#include "config.h"
diff --git a/tst/test-el-pbinary.c b/tst/test-el-pbinary.c
new file mode 100644
index 0000000..23e0620
--- /dev/null
+++ b/tst/test-el-pbinary.c
@@ -0,0 +1,670 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ========================================================================== */
+
+
+/* ==========================================================================
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
+
+ ========================================================================== */
+
+
+#include <ctype.h>
+#include <errno.h>
+#include <libgen.h>
+#include <rb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdlib.h>
+
+#include "mtest.h"
+#include "el-private.h"
+
+
+/* ==========================================================================
+ _ __ __
+ ____ _____ (_)_ __ ____ _ / /_ ___ / /_ __ __ ____ ___ _____
+ / __ \ / ___// /| | / // __ `// __// _ \ / __// / / // __ \ / _ \ / ___/
+ / /_/ // / / / | |/ // /_/ // /_ / __/ / /_ / /_/ // /_/ // __/(__ )
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/ \__/ \__, // .___/ \___//____/
+/_/ /____//_/
+
+ ========================================================================== */
+
+
+struct log_message
+{
+ const unsigned char *msg;
+ size_t msglen;
+ int level;
+};
+
+
+/* ==========================================================================
+ _ __
+ ____ _____ (_)_ __ ____ _ / /_ ___
+ / __ \ / ___// /| | / // __ `// __// _ \
+ / /_/ // / / / | |/ // /_/ // /_ / __/
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/
+ /_/
+ _ __ __
+ _ __ ____ _ _____ (_)____ _ / /_ / /___ _____
+ | | / // __ `// ___// // __ `// __ \ / // _ \ / ___/
+ | |/ // /_/ // / / // /_/ // /_/ // // __/(__ )
+ |___/ \__,_//_/ /_/ \__,_//_.___//_/ \___//____/
+
+ ========================================================================== */
+
+
+mt_defs_ext();
+static const char *logpath = "/tmp/embedlog-pbinary-test";
+static struct rb *expected_logs; /* array of expected logs */
+static int truncate_test;
+
+static unsigned char d1[] = { 0x01 };
+static unsigned char d2[] = { 0x53, 0x10 };
+static unsigned char d3[] = { 0x00, 0x10, 0x12 };
+static unsigned char d5[] = { 'f', 'o', 'o', 0x00, 'b' };
+static unsigned char d8[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 };
+
+
+/* ==========================================================================
+ _ __
+ ____ _____ (_)_ __ ____ _ / /_ ___
+ / __ \ / ___// /| | / // __ `// __// _ \
+ / /_/ // / / / | |/ // /_/ // /_ / __/
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ Checks if el_print function prints everything in well-defined format.
+ This function cross-checks logbuf buffer where el_print function prints
+ message into, and expected_logs with raw information about what should
+ be printed.
+ ========================================================================== */
+
+
+static int pbinary_check(void)
+{
+ struct log_message expected;
+ struct stat st;
+ unsigned char *msg;
+ unsigned char *msgsave;
+ int fd;
+ unsigned char tmp[1024];
+ int i;
+ int slevel;
+ size_t msglen;
+ size_t len;
+ unsigned char flags;
+ unsigned long long val;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ stat(logpath, &st);
+ fd = open(logpath, O_RDONLY);
+ msg = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ msgsave = msg;
+
+ while (rb_read(expected_logs, &expected, 1) == 1)
+ {
+ slevel = expected.level > EL_DBG ? EL_DBG : expected.level;
+
+ if (expected.level > g_options.level)
+ {
+ /*
+ * log should not have been printed due to current log level
+ * restriction. We just continue here, because if log was indeed
+ * printed, next checks will fail anyway.
+ */
+
+ continue;
+ }
+
+ /*
+ * read flags
+ */
+
+ flags = *msg++;
+
+ /*
+ * check if level is added to flags
+ */
+
+ if ((flags >> 3) != expected.level)
+ {
+ /*
+ * no, its not set correctly
+ */
+
+ goto error;
+ }
+
+ /*
+ * check printing timestamp
+ */
+
+ if (g_options.timestamp != EL_TS_OFF)
+ {
+ unsigned long long tmp;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ len = el_decode_number(msg, &tmp);
+ msg += len;
+
+ /*
+ * we don't know exact time embedlog put into log file, so we
+ * have to trust the size
+ */
+
+ if (flags & 0x01 != 0x01)
+ {
+ /*
+ * expected timestamp flag to be set
+ */
+
+ goto error;
+ }
+
+ /*
+ * fraction of seconds checks makes sense only when ts is set
+ */
+
+ if (g_options.timestamp_useconds)
+ {
+ unsigned long long usec;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ len = el_decode_number(msg, &usec);
+ msg += len;
+
+ if (usec > 999999)
+ {
+ /*
+ * we can't check exact value of microseconds, but we surely
+ * can check if this value is not too big (and thus corrupt)
+ */
+
+ goto error;
+ }
+
+ if (flags & 0x04 != 0x04)
+ {
+ /*
+ * usec not set, and should be
+ */
+
+ goto error;
+ }
+ }
+ else
+ {
+ if (flags & 0x06)
+ {
+ /*
+ * fraction flags set, and should not be
+ */
+
+ goto error;
+ }
+ }
+
+
+ }
+ else
+ {
+ if (flags & 0x01)
+ {
+ /*
+ * we didn't expect timestamp flag to be set
+ */
+
+ goto error;
+ }
+
+ if (flags & 0x06)
+ {
+ /*
+ * when timestamp is not set, we expect fraction of seconds
+ * to not be set as well
+ */
+
+ goto error;
+ }
+ }
+
+ /*
+ * now we can check printed data
+ */
+
+ if (truncate_test)
+ {
+ int i;
+ int written;
+ char expect[EL_BUF_MAX];
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ for (i = 0; i != sizeof(expect); ++i)
+ {
+ expect[i] = (unsigned char)i;
+ }
+
+ written = msg - msgsave;
+
+ len = el_decode_number(msg, &val);
+
+ if (val != EL_BUF_MAX - written - len)
+ {
+ /*
+ * truncated message has wrong length
+ */
+
+ return -1;
+ }
+
+ msg += len;
+
+ if (memcmp(msg, expect, val) != 0)
+ {
+ /*
+ * data is incorrect
+ */
+
+ return -1;
+ }
+
+ /*
+ * point to next message
+ */
+
+ msg += val;
+ }
+ else
+ {
+ len = el_decode_number(msg, &val);
+ msg += len;
+
+ if (memcmp(msg, expected.msg, val) != 0)
+ {
+ /*
+ * data different than expected
+ */
+
+ goto error;
+ }
+
+ /*
+ * finally set msg to point to next message
+ */
+
+ msg += val;
+ }
+ }
+
+ munmap(msgsave, st.st_size);
+ close(fd);
+ return 0;
+
+error:
+ munmap(msgsave, st.st_size);
+ close(fd);
+ return 1;
+}
+
+
+/* ==========================================================================
+ adds log to array of expected logs and then sends passed log message
+ into el_print
+ ========================================================================== */
+
+
+static void add_log
+(
+ enum el_level level,
+ const void *mem,
+ size_t mlen
+)
+{
+ struct log_message expected;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ expected.level = level;
+ expected.msg = mem;
+ expected.msglen = mlen;
+ rb_write(expected_logs, &expected, 1);
+ el_pbinary(level, mem, mlen);
+}
+
+
+/* ==========================================================================
+ Called before every test, initializes embedlog to known state, and
+ allocates memory for expected_logs buffer
+ ========================================================================== */
+
+
+static void test_prepare(void)
+{
+ el_init();
+ unlink(logpath);
+ el_option(EL_PRINT_LEVEL, 0);
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_PREFIX, NULL);
+ el_option(EL_COLORS, 0);
+ el_option(EL_TS, EL_TS_OFF);
+ el_option(EL_TS_USEC, 0);
+ el_option(EL_PRINT_LEVEL, 0);
+ el_option(EL_FROTATE_NUMBER, 0);
+ el_option(EL_FILE_SYNC_EVERY, 1024);
+ el_option(EL_FPATH, logpath);
+ truncate_test = 0;
+ expected_logs = rb_new(1024, sizeof(struct log_message), 0);
+}
+
+
+/* ==========================================================================
+ Called after every test. Frees all memory allocated by test_prepare
+ ========================================================================== */
+
+
+static void test_cleanup(void)
+{
+ el_cleanup();
+ rb_destroy(expected_logs);
+ unlink(logpath);
+}
+
+
+/* ==========================================================================
+ __ __
+ / /_ ___ _____ / /_ _____
+ / __// _ \ / ___// __// ___/
+ / /_ / __/(__ )/ /_ (__ )
+ \__/ \___//____/ \__//____/
+
+ ========================================================================== */
+
+
+static void pbinary_simple_message(void)
+{
+ add_log(EL_FATAL, d5, 5);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_simple_multiple_message(void)
+{
+ add_log(EL_FATAL, d1, 1);
+ add_log(EL_FATAL, d2, 2);
+ add_log(EL_FATAL, d5, 5);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_ts_without_fractions(void)
+{
+ el_option(EL_TS_USEC, 1);
+ add_log(EL_FATAL, d1, 1);
+ add_log(EL_FATAL, d2, 2);
+ add_log(EL_FATAL, d5, 5);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_timestamp_short(void)
+{
+ el_option(EL_TS, EL_TS_SHORT);
+ add_log(EL_FATAL, d2, 2);
+ add_log(EL_FATAL, d5, 5);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_timestamp_long(void)
+{
+ el_option(EL_TS, EL_TS_LONG);
+ add_log(EL_FATAL, d2, 2);
+ add_log(EL_FATAL, d5, 5);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_timestamp_short_no_useconds(void)
+{
+ el_option(EL_TS_USEC, 0);
+ el_option(EL_TS, EL_TS_SHORT);
+ add_log(EL_FATAL, d2, 2);
+ add_log(EL_FATAL, d5, 5);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_timestamp_long_no_useconds(void)
+{
+ el_option(EL_TS_USEC, 0);
+ el_option(EL_TS, EL_TS_LONG);
+ add_log(EL_FATAL, d2, 2);
+ add_log(EL_FATAL, d5, 5);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_different_clocks(void)
+{
+ int i;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ for (i = EL_TS_TM_CLOCK; i != EL_TS_TM_ERROR; ++i)
+ {
+ test_prepare();
+ el_option(EL_TS_TM, i);
+ el_option(EL_TS, EL_TS_LONG);
+ add_log(EL_FATAL, d8, 8);
+ add_log(EL_FATAL, d8, 8);
+ mt_fok(pbinary_check());
+ test_cleanup();
+ }
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_mix_of_everything(void)
+{
+ int level;
+ int timestamp;
+ int printlevel;
+ int finfo;
+ int colors;
+ int prefix;
+ int usec;
+ int nl;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ for (level = EL_FATAL; level <= EL_DBG; ++level)
+ for (timestamp = EL_TS_OFF; timestamp != EL_TS_ERROR; ++timestamp)
+ for (printlevel = 0; printlevel <= 1; ++printlevel)
+ for (finfo = 0; finfo <= 1; ++finfo)
+ for (colors = 0; colors <= 1; ++colors)
+ for (prefix = 0; prefix <= 1; ++prefix)
+ for (usec = 0; usec <= 1; ++usec)
+ for (nl = 0; nl <= 1; ++nl)
+ {
+ test_prepare();
+ el_option(EL_LEVEL, level);
+ el_option(EL_TS, timestamp);
+ el_option(EL_PRINT_LEVEL, printlevel);
+ el_option(EL_PRINT_NL, nl);
+ el_option(EL_FINFO, finfo);
+ el_option(EL_COLORS, colors);
+ el_option(EL_PREFIX, prefix ? "prefix" : NULL);
+
+ add_log(EL_FATAL, d1, 1);
+ add_log(EL_ALERT, d1, 1);
+ add_log(EL_CRIT, d1, 1);
+ add_log(EL_ERROR, d5, 5);
+ add_log(EL_WARN, d1, 1);
+ add_log(EL_NOTICE, d2, 2);
+ add_log(EL_INFO, d1, 1);
+ add_log(EL_DBG, d8, 8);
+
+ /*
+ * cleanup so embedlog closes test file, which will flush data into
+ * disk so pbinary_check() can read that data
+ */
+
+ el_cleanup();
+ mt_fok(pbinary_check());
+
+ test_cleanup();
+ }
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_with_no_output_available(void)
+{
+ el_option(EL_OUT, EL_OUT_NONE);
+ mt_ferr(el_pbinary(EL_INFO, d2, 2), ENODEV);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_level_not_high_enough(void)
+{
+ mt_ferr(el_pbinary(EL_DBG, d8, 8), ERANGE);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_null(void)
+{
+ mt_ferr(el_pbinary(EL_ALERT, NULL, 0), EINVAL);
+ mt_ferr(el_pbinary(EL_ALERT, NULL, 5), EINVAL);
+ mt_ferr(el_pbinary(EL_ALERT, d5, 0), EINVAL);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void pbinary_truncate(void)
+{
+ int i;
+ char msg[EL_BUF_MAX + 3];
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ for (i = 0; i != sizeof(msg); ++i)
+ {
+ msg[i] = (unsigned char)i;
+ }
+
+ el_option(EL_TS, EL_TS_LONG);
+ el_option(EL_TS_USEC, 1);
+ add_log(EL_INFO, msg, sizeof(msg));
+
+ /*
+ * tell checker that this is truncate test
+ */
+
+ truncate_test = 1;
+ mt_fok(pbinary_check());
+}
+
+/* ==========================================================================
+ __ __
+ / /_ ___ _____ / /_ ____ _ _____ ____ __ __ ____
+ / __// _ \ / ___// __/ / __ `// ___// __ \ / / / // __ \
+ / /_ / __/(__ )/ /_ / /_/ // / / /_/ // /_/ // /_/ /
+ \__/ \___//____/ \__/ \__, //_/ \____/ \__,_// .___/
+ /____/ /_/
+ ========================================================================== */
+
+
+void el_pbinary_test_group(void)
+{
+ mt_run(pbinary_different_clocks);
+ mt_run(pbinary_mix_of_everything);
+
+ mt_prepare_test = &test_prepare;
+ mt_cleanup_test = &test_cleanup;
+
+ mt_run(pbinary_simple_message);
+ mt_run(pbinary_simple_multiple_message);
+ mt_run(pbinary_ts_without_fractions);
+ mt_run(pbinary_timestamp_short);
+ mt_run(pbinary_timestamp_long);
+ mt_run(pbinary_timestamp_short_no_useconds);
+ mt_run(pbinary_timestamp_long_no_useconds);
+ mt_run(pbinary_with_no_output_available);
+ mt_run(pbinary_level_not_high_enough);
+ mt_run(pbinary_null);
+ mt_run(pbinary_truncate);
+} \ No newline at end of file
diff --git a/tst/test-el-print.c b/tst/test-el-print.c
index 3af3e52..f8d23c3 100644
--- a/tst/test-el-print.c
+++ b/tst/test-el-print.c
@@ -24,8 +24,7 @@
#include "stdlib.h"
#include "embedlog.h"
-#include "config-priv.h"
-#include "el-options.h"
+#include "el-private.h"
/* ==========================================================================
diff --git a/tst/test-group-list.h b/tst/test-group-list.h
index 4429a42..cd478cf 100644
--- a/tst/test-group-list.h
+++ b/tst/test-group-list.h
@@ -8,6 +8,7 @@
void el_options_test_group(void);
void el_print_test_group(void);
+void el_pbinary_test_group(void);
void el_file_test_group(void);
void el_perror_test_group(void);
void el_pmemory_test_group(void);