aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Łyszczek <michal.lyszczek@bofc.pl>2017-08-13 20:32:32 +0200
committerMichał Łyszczek <michal.lyszczek@bofc.pl>2017-08-13 20:32:32 +0200
commit335c2197c16b1d36d3549c9614b52df5c2545397 (patch)
treeb9b706d85d6d7356e95c0c9cd4af6258c49b8623
parentfac685704ed47e391c038ecc25eb1a46ab1069aa (diff)
downloadembedlog-335c2197c16b1d36d3549c9614b52df5c2545397.tar.gz
embedlog-335c2197c16b1d36d3549c9614b52df5c2545397.tar.bz2
embedlog-335c2197c16b1d36d3549c9614b52df5c2545397.zip
Added feature to print log to file
-rw-r--r--configure.ac45
-rw-r--r--include/embedlog.h30
-rw-r--r--src/Makefile.am10
-rw-r--r--src/el-file.c403
-rw-r--r--src/el-file.h15
-rw-r--r--src/el-puts.c9
-rw-r--r--src/options.c230
7 files changed, 645 insertions, 97 deletions
diff --git a/configure.ac b/configure.ac
index 8e16d9b..f8b07fe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -8,11 +8,11 @@ AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_HEADERS([config.h])
-#
+###
# --enable-feature options
#
-#
+###
# --enable-out-stderr
#
@@ -31,8 +31,28 @@ AS_IF([test "x$enable_out_stderr" = "xyes"],
enable_out_stderr="no"
])
-
+###
+# --enable-out-file
#
+
+
+AC_ARG_ENABLE([out-file],
+ AS_HELP_STRING([--enable-out-file], [Enable printing to file]))
+
+AM_CONDITIONAL([ENABLE_OUT_FILE], [test "x$enable_out_file" = "xyes"])
+AS_IF([test "x$enable_out_file" = "xyes"],
+[
+ AC_DEFINE([ENABLE_OUT_FILE], [1], [Enable printing to file])
+ AC_CHECK_FUNCS([fopen fclose fwrite remove rename],,
+ AC_MSG_ERROR(not found, needed by --enable-out-file))
+],
+# else
+[
+ enable_out_file="no"
+])
+
+
+###
# --enable-timestamp
#
@@ -52,7 +72,7 @@ AS_IF([test "x$enable_timestamp" = "xyes"],
])
-#
+###
# --enable-realtime
#
@@ -77,7 +97,7 @@ AS_IF([test "x$enable_realtime" = "xyes"],
])
-#
+###
# --enable-monotonic
#
@@ -102,7 +122,7 @@ AS_IF([test "x$enable_monotonic" = "xyes"],
])
-#
+###
# --enable-finfo
#
@@ -122,7 +142,7 @@ AS_IF([test "x$enable_finfo" = "xyes"],
])
-#
+###
# --enable-colors
#
@@ -142,7 +162,7 @@ AS_IF([test "x$enable_colors" = "xyes"],
])
-#
+###
# --enable-reentrant
#
@@ -162,12 +182,12 @@ AS_IF([test "x$enable_reentrant" = "xyes"],
])
-#
+###
# VARIABLES=value options
#
-#
+###
# EL_LOG_MAX
#
@@ -177,7 +197,7 @@ AS_IF([test "x$EL_LOG_MAX" = x], [EL_LOG_MAX="2 * 1024"])
AC_DEFINE_UNQUOTED([EL_LOG_MAX], [$EL_LOG_MAX], [Maximum size of log message])
-#
+###
# EL_FLEN_MAX
#
@@ -186,7 +206,7 @@ AC_ARG_VAR([EL_FLEN_MAX], [Maximum size of file in message])
AS_IF([test "x$EL_FLEN_MAX" = x], [EL_FLEN_MAX="32"])
AC_DEFINE_UNQUOTED([EL_FLEN_MAX], [$EL_FLEN_MAX], [Maximum size of file in message])
-#
+###
# EL_MEM_LINE_SIZE
#
@@ -204,6 +224,7 @@ echo
echo "embedlog compilation configuration summary"
echo
echo "print to stderr............. : $enable_out_stderr"
+echo "print to file............... : $enable_out_file"
echo "print timestamp enabled..... : $enable_timestamp"
echo "clock_realtime timestamp.... : $enable_realtime"
echo "clock_monotonic timestamp... : $enable_monotonic"
diff --git a/include/embedlog.h b/include/embedlog.h
index 7f1f1ca..fcb3231 100644
--- a/include/embedlog.h
+++ b/include/embedlog.h
@@ -9,6 +9,7 @@
#include <stddef.h>
#include <stdarg.h>
+#include <stdio.h>
#define ELE EL_LEVEL_ERR, __FILE__, __LINE__
#define ELW EL_LEVEL_WRN, __FILE__, __LINE__
@@ -39,7 +40,13 @@ enum el_option
EL_OPT_COLORS,
EL_OPT_TS,
EL_OPT_TS_TM,
+
EL_OPT_FINFO,
+ EL_OPT_FNAME,
+ EL_OPT_FROTATE_NUMBER,
+ EL_OPT_FROTATE_SIZE,
+
+ EL_OPT_ERROR /* internal use only */
};
enum el_option_timestamp
@@ -59,12 +66,19 @@ enum el_option_timestamp_timer
struct el_options
{
- int outputs;
- int level;
- int colors;
- int timestamp;
- int timestamp_timer;
- int finfo;
+ int outputs;
+ int level;
+ int colors;
+ int timestamp;
+ int timestamp_timer;
+
+ int finfo;
+ int frotate_number;
+ int fcurrent_rotate;
+ long frotate_size;
+ long fpos;
+ FILE *file;
+ const char *fname;
};
int el_options_init(struct el_options *);
@@ -74,8 +88,8 @@ int el_output_enable(enum el_output);
int el_ooutput_enable(struct el_options *, enum el_output);
int el_output_disable(enum el_output);
int el_ooutput_disable(struct el_options *, enum el_output);
-int el_option(enum el_option, int);
-int el_ooption(struct el_options *, enum el_option, int);
+int el_option(enum el_option, ...);
+int el_ooption(struct el_options *, enum el_option, ...);
int el_puts(const char *);
int el_oputs(struct el_options *, const char *s);
int el_print(enum el_level, const char *, size_t, const char *, ...);
diff --git a/src/Makefile.am b/src/Makefile.am
index 706092e..e3f4b86 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,10 +1,20 @@
lib_LTLIBRARIES = libembedlog.la
libembedlog_la_SOURCES = el-print.c el-puts.c el-perror.c el-pmemory.c options.c
+
+if ENABLE_OUT_FILE
+libembedlog_la_SOURCES += el-file.c
+endif
+
libembedlog_la_LDFLAGS = -version-info 0:0:0
libembedlog_la_CFLAGS = -I$(top_srcdir)/include
bin_PROGRAMS = test
test_SOURCES = el-print.c el-puts.c el-perror.c el-pmemory.c options.c main.c
+
+if ENABLE_OUT_FILE
+test_SOURCES += el-file.c
+endif
+
test_CFLAGS = -I$(top_srcdir)/include -O0 -g3 -ggdb
TESTS = $(check_PROGRAMS)
diff --git a/src/el-file.c b/src/el-file.c
new file mode 100644
index 0000000..ed05117
--- /dev/null
+++ b/src/el-file.c
@@ -0,0 +1,403 @@
+/* ==========================================================================
+ Licensed under BSD 2clause license See LICENSE file for more information
+ Author: Michał Łyszczek <michal.lyszczek@bofc.pl>
+ ==========================================================================
+
+ -------------------------------------------------------------
+ / module designated to print messages into files, it also has \
+ \ capabilities to rotate files if user wishes to /
+ -------------------------------------------------------------
+ \ \ /
+ \ \/
+ (__) /\
+ (oo) O O
+ _\/_ //
+ * ( ) //
+ \ (\\ //
+ \( \\ )
+ ( \\ ) /\
+ ___[\______/^^^^^^^\__/) o-)__
+ |\__[=======______//________)__\
+ \|_______________//____________|
+ ||| || //|| |||
+ ||| || @.|| |||
+ || \/ .\/ ||
+ . .
+ '.'.`
+
+ COW-OPERATION
+ ========================================================================== */
+
+
+/* ==========================================================================
+ _ __ __ ____ _ __
+ (_)____ _____ / /__ __ ____/ /___ / __/(_)/ /___ _____
+ / // __ \ / ___// // / / // __ // _ \ / /_ / // // _ \ / ___/
+ / // / / // /__ / // /_/ // /_/ // __/ / __// // // __/(__ )
+ /_//_/ /_/ \___//_/ \__,_/ \__,_/ \___/ /_/ /_//_/ \___//____/
+
+ ========================================================================== */
+
+
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "options.h"
+
+
+/* ==========================================================================
+ _ __
+ ____ _____ (_)_ __ ____ _ / /_ ___
+ / __ \ / ___// /| | / // __ `// __// _ \
+ / /_/ // / / / | |/ // /_/ // /_ / __/
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ checks if we can (or should) write to a file
+ ========================================================================== */
+
+
+static int el_file_is_writeable
+(
+ struct el_options *options, /* file options */
+ size_t slen /* length of string caller wants to print */
+)
+{
+ if (options->file == NULL)
+ {
+ /*
+ * well, it's hard to write to a file if it is not opened
+ */
+
+ return 0;
+ }
+
+ if (options->fpos + slen > options->frotate_size)
+ {
+ /*
+ * writing to file, would overflow it (according to frotate_size
+ * set by user), so write should no be allowed.
+ */
+
+ return 0;
+ }
+
+ return 1;
+}
+
+
+/* ==========================================================================
+ function rotates file, meaning if currently opened file has suffix .3,
+ function will close that file and will open file with suffix .4. If
+ creating new suffix is impossible (we reached frotate_number of
+ suffixed) function will rename files, and create new file with suffix .0
+ ========================================================================== */
+
+
+static int el_file_rotate
+(
+ struct el_options *options
+)
+{
+ char path[PATH_MAX + 1]; /* path to log file we will open */
+ int i; /* simple iterator for loop */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ if (options->file)
+ {
+ fclose(options->file);
+ options->file = NULL;
+ }
+
+ options->fcurrent_rotate++;
+ if (options->fcurrent_rotate == options->frotate_number)
+ {
+ /*
+ * it appears we used all rotating slots, reset counter and rename
+ * all files in order (for frotate_number == 4)
+ *
+ * .1 -> .0
+ * .2 -> .1
+ * .3 -> .2
+ *
+ * As we can see, oldest file .0 will be deleted, and file .3 will
+ * disapear making space for new log
+ */
+
+ options->fcurrent_rotate = options->frotate_number - 1;
+
+ if (options->frotate_number == 1)
+ {
+ /*
+ * if frotate_number is equal to 1, this means only one file can
+ * exist (with suffix .0), so we cannot rotate that (like rename
+ * it from .0 to .0, pointless) file and thus we simply skip
+ * this foor loop, and later file will just be truncated to 0
+ */
+
+ goto skip_rotate;
+ }
+
+ for (i = 1; i != options->frotate_number; ++i)
+ {
+ char old_name[PATH_MAX + 1]; /* ie .2 suffix */
+ char new_name[PATH_MAX + 1]; /* ie .3 suffix */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ /*
+ * we do not check for overflow here, as overflow is already
+ * tested in el_file_open function, there we check opening file
+ * with biggest suffix. Assuming if it works there, it will work
+ * here as well
+ */
+
+ sprintf(old_name, "%s.%d", options->fname, i);
+ sprintf(new_name, "%s.%d", options->fname, i - 1);
+
+ rename(old_name, new_name);
+
+ /*
+ * rename can fail, but it is usually because someone removed
+ * some logs, like there are logs: .1 .2 .4 .5, so .3 is
+ * missing, and if we want to rename .3 to .2, rename will fail,
+ * it doesn't really matter, as .4 will be renamed to .3, and
+ * after full loop there will be .0 .1 .3 .4 .5 and after one
+ * more rotation, we'll have .0 .1 .2 .3 .4 .5, so full complet.
+ * So such situation will heal by itself over time.
+ */
+ }
+ }
+
+skip_rotate:
+ /*
+ * now we can safely open file with suffix .0, we're sure we won't
+ * overwrite anything (well except if someone sets frotate_number to 1,
+ * then current .0 file will be truncated). We don't need to check for
+ * length of created file, as it is checked in el_file_open and if it
+ * passes there, it will pass here as well
+ */
+
+ sprintf(path, "%s.%d", options->fname, options->fcurrent_rotate);
+
+ if ((options->file = fopen(path, "w")) == NULL)
+ {
+ return -1;
+ }
+
+ options->fpos = ftell(options->file);
+ return 0;
+}
+
+/* ==========================================================================
+ __ __ _
+ ____ __ __ / /_ / /(_)_____
+ / __ \ / / / // __ \ / // // ___/
+ / /_/ // /_/ // /_/ // // // /__
+ / .___/ \__,_//_.___//_//_/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ opens log file specified in options and sets file position, so we can
+ track it.
+ ========================================================================== */
+
+
+int el_file_open
+(
+ struct el_options *options /* options with file information */
+)
+{
+ if (options->file)
+ {
+ /*
+ * to prevent any memory leak in case of double open, we first
+ * close already opened file Such situation may happen when library
+ * user changes file name using EL_OPT_FNAME option,
+ */
+
+ fclose(options->file);
+ options->file = NULL;
+ }
+
+ if (options->frotate_number)
+ {
+ FILE *f; /* opened file */
+ int i; /* simple interator for loop */
+ char path[PATH_MAX + 1]; /* file path + suffix = file to open */
+ size_t pathl; /* length of path after snprintf */
+ long fsize; /* size of the opened file */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ path[0] = '\0';
+
+ /*
+ * file rotation is enabled, in such case we need to find, oldest
+ * rotate file, as app could have been restarted, and we surely
+ * don't want to overwrite the newest file. Newest file has suffix
+ * .0 while the oldest one has suffix .${frotate_number} (or less
+ * if there is less files).
+ */
+
+ for (i = options->frotate_number - 1; i >= 0; --i)
+ {
+ pathl = snprintf(path, PATH_MAX + 1, "%s.%d", options->fname, i);
+
+ if (pathl > PATH_MAX)
+ {
+ /*
+ * path is too long, we cannot safely create file with
+ * suffix, return error as opening such truncated file name
+ * could result in some data lose on the disk.
+ */
+
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ if ((f = fopen(path, "a")) == NULL)
+ {
+ /*
+ * if we cannot open file, that means there is some kind of
+ * error, like permision denied or system is out of memory,
+ * it's pointless to continue
+ */
+
+ return -1;
+ }
+
+ if (i == 0)
+ {
+ /*
+ * this is the last file we check, we don't check for file
+ * size here, since even if this file is empty, we are sure
+ * this is the oldest file. File is already opened so, we
+ * simply return from the function
+ */
+
+ options->fcurrent_rotate = i;
+ options->fpos = ftell(f);
+ options->file = f;
+ return 0;
+ }
+
+ if ((fsize = ftell(f)) == 0)
+ {
+ /*
+ * we've created (or opened ) an empty file, this means our
+ * file is not the oldest one, i.e. we opened file .6 and
+ * oldest could be .3. We remove this file and continue our
+ * search for the glory file.
+ */
+
+ fclose(f);
+ remove(path);
+ continue;
+ }
+
+ /*
+ * oldest file found, file is already opened so we simply return
+ * from the function
+ */
+
+ options->fcurrent_rotate = i;
+ options->fpos = fsize;
+ options->file = f;
+ return 0;
+ }
+ }
+
+ /*
+ * rotation is disabled, simply open file with append flag
+ */
+
+ if ((options->file = fopen(options->fname, "a")) == NULL)
+ {
+ return -1;
+ }
+
+ options->fpos = ftell(options->file);
+ return 0;
+}
+
+
+/* ==========================================================================
+ puts string s into file from options, if needed also rotates files
+ ========================================================================== */
+
+
+int el_file_puts
+(
+ struct el_options *options, /* printing options */
+ const char *s /* string to 'put' into file */
+)
+{
+ int sl; /* size of the s message */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ sl = strlen(s);
+
+ if (options->frotate_number && el_file_is_writeable(options, sl) == 0)
+ {
+ /*
+ * we get here only when frotate is enabled, and writing to current
+ * file would result in exceding frotate_size of file. In suche case
+ * we rotate the file by closing the old one and opening new file,
+ * and if we already filled frotate_number files, we remove the
+ * oldest one, unless frotate_number is -1, then we rotate without
+ * deleting anything.
+ */
+
+ if (el_file_rotate(options) != 0)
+ {
+ return -1;
+ }
+ }
+
+ if (fwrite(s, sl, 1, options->file) != 1)
+ {
+ return -1;
+ }
+
+ fflush(options->file);
+ options->fpos += sl;
+ return 0;
+}
+
+
+/* ==========================================================================
+ free resources allocated by this module
+ ========================================================================== */
+
+
+void el_file_cleanup
+(
+ struct el_options *options /* file options */
+)
+{
+ if (options->file)
+ {
+ fclose(options->file);
+ }
+}
diff --git a/src/el-file.h b/src/el-file.h
new file mode 100644
index 0000000..56087be
--- /dev/null
+++ b/src/el-file.h
@@ -0,0 +1,15 @@
+/* ==========================================================================
+ 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
+
+#include "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-puts.c b/src/el-puts.c
index 4459e02..0076714 100644
--- a/src/el-puts.c
+++ b/src/el-puts.c
@@ -33,6 +33,7 @@
#include <stdio.h>
+#include "el-file.h"
#include "embedlog.h"
#include "options.h"
@@ -82,7 +83,7 @@ int el_oputs
#if ENABLE_OUT_STDERR
if (options->outputs & EL_OUT_STDERR)
{
- fputs(s, stderr);
+ return fputs(s, stderr) == EOF ? -1 : 0;
}
#endif
@@ -91,12 +92,16 @@ int el_oputs
{
el_puts_syslog(s);
}
+#endif
+#if ENABLE_OUT_FILE
if (options->outputs & EL_OUT_FILE)
{
- el_puts_file(s);
+ return el_file_puts(options, s);
}
+#endif
+#if 0
if (options->outputs & EL_OUT_NET)
{
el_puts_net(s);
diff --git a/src/options.c b/src/options.c
index 303bdf3..e74affb 100644
--- a/src/options.c
+++ b/src/options.c
@@ -43,6 +43,7 @@
#include "embedlog.h"
#include "options.h"
#include "valid.h"
+#include "el-file.h"
/* ==========================================================================
@@ -82,26 +83,146 @@ struct el_options g_options;
static const int VALID_OUTS = 0
- #if ENABLE_OUT_STDERR
- | EL_OUT_STDERR
- #endif
+#if ENABLE_OUT_STDERR
+ | EL_OUT_STDERR
+#endif
- #if ENABLE_OUT_SYSLOG
- | EL_OUT_SYSLOG
- #endif
+#if ENABLE_OUT_SYSLOG
+ | EL_OUT_SYSLOG
+#endif
+
+#if ENABLE_OUT_FILE
+ | EL_OUT_FILE
+#endif
+
+#if ENABLE_OUT_NET
+ | EL_OUT_NET
+#endif
+
+#if ENABLE_OUT_TTY
+ | EL_OUT_TTY
+#endif
+ ;
+
+
+/* ==========================================================================
+ _ __
+ ____ _____ (_)_ __ ____ _ / /_ ___
+ / __ \ / ___// /| | / // __ `// __// _ \
+ / /_/ // / / / | |/ // /_/ // /_ / __/
+ / .___//_/ /_/ |___/ \__,_/ \__/ \___/
+ /_/
+ ____ __ _
+ / __/__ __ ____ _____ / /_ (_)____ ____ _____
+ / /_ / / / // __ \ / ___// __// // __ \ / __ \ / ___/
+ / __// /_/ // / / // /__ / /_ / // /_/ // / / /(__ )
+ /_/ \__,_//_/ /_/ \___/ \__//_/ \____//_/ /_//____/
+
+ ========================================================================== */
+
+
+/* ==========================================================================
+ sets 'option' with 'ap' values in 'options' object.
+
+ errno
+ EINVAL option is invalid
+ EINVAL value for specific option is invalid
+ ENOSYS option was disabled during compilation
+ ========================================================================== */
+
+
+static int el_vooption
+(
+ struct el_options *options, /* options object to set option to */
+ enum el_option option, /* option to set */
+ va_list ap /* option value(s) */
+)
+{
+ int value_int; /* ap value treated as integer */
+ long value_long; /* ap value treated as long */
+ const char *value_str; /* ap value treated as string */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+ VALID(EINVAL, 0 <= option && option <= EL_OPT_ERROR);
+
+ switch (option)
+ {
+ #if ENABLE_COLORS
+
+ case EL_OPT_COLORS:
+ /*
+ * only 1 or 0 is allowed, if any other bit is set return EINVAL
+ */
+
+ value_int = va_arg(ap, int);
+ VALID(EINVAL, (value_int & ~1) == 0);
+
+ options->colors = value_int;
+ return 0;
+
+ #endif /* ENABLE_COLORS */
+
+ #if ENABLE_TIMESTAMP
+
+ case EL_OPT_TS:
+ value_int = va_arg(ap, int);
+ VALID(EINVAL, 0 <= value_int && value_int <= EL_OPT_TS_OFF);
+
+ options->timestamp = value_int;
+ return 0;
+
+ case EL_OPT_TS_TM:
+ value_int = va_arg(ap, int);
+ VALID(EINVAL, 0 <= value_int && value_int <= EL_OPT_TS_TM_MONOTONIC);
+
+ options->timestamp_timer = value_int;
+ return 0;
+
+ #endif /* ENABLE_TIMESTAMP */
+
+ #if ENABLE_FINFO
+
+ case EL_OPT_FINFO:
+ value_int = va_arg(ap, int);
+ VALID(EINVAL, (value_int & ~1) == 0);
+
+ options->finfo = value_int;
+ return 0;
+
+ #endif /* ENABLE_FINFO */
#if ENABLE_OUT_FILE
- | EL_OUT_FILE
- #endif
- #if ENABLE_OUT_NET
- | EL_OUT_NET
- #endif
+ case EL_OPT_FNAME:
+ value_str = va_arg(ap, const char *);
+ options->fname = value_str;
+ return el_file_open(options);
+
+ case EL_OPT_FROTATE_NUMBER:
+ value_int = va_arg(ap, int);
+ VALID(EINVAL, value_int >= 0);
+ options->frotate_number = value_int;
+ return 0;
- #if ENABLE_OUT_TTY
- | EL_OUT_TTY
- #endif
- ;
+ case EL_OPT_FROTATE_SIZE:
+ value_long = va_arg(ap, long);
+ VALID(EINVAL, value_long >= 1);
+ options->frotate_size = value_long;
+ return 0;
+
+ #endif /* ENABLE_OUT_FILE */
+
+ default:
+ /*
+ * if we get here, user used option that was disabled during compilation
+ * time and is not implemented
+ */
+
+ errno = ENOSYS;
+ return -1;
+ }
+}
/* ==========================================================================
@@ -278,20 +399,23 @@ int el_log_allowed
int el_option
(
enum el_option option, /* option to set */
- int value /* option value */
+ ... /* option value */
)
{
- return el_ooption(&g_options, option, value);
+ va_list ap; /* variadic arguments */
+ int rc; /* return code from el_voooption */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ va_start(ap, option);
+ rc = el_vooption(&g_options, option, ap);
+ va_end(ap);
+
+ return rc;
}
/* ==========================================================================
- sets 'option' with 'value' in 'options' object.
-
- errno
- EINVAL option is invalid
- EINVAL value for specific option is invalid
- ENOSYS option was disabled during compilation
+ same as el_vooptions but accepts variadic arguments
========================================================================== */
@@ -299,61 +423,17 @@ int el_ooption
(
struct el_options *options, /* options object to set option to */
enum el_option option, /* option to set */
- int value /* option value */
+ ... /* option value(s) */
)
{
- VALID(EINVAL, 0 <= option && option <= EL_OPT_FINFO);
+ va_list ap; /* variadic arguments */
+ int rc; /* return code from el_voooption */
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- switch (option)
- {
- #if ENABLE_COLORS
-
- case EL_OPT_COLORS:
- /*
- * only 1 or 0 is allowed, if any other bit is set return EINVAL
- */
- VALID(EINVAL, (value & ~1) == 0);
+ va_start(ap, option);
+ rc = el_vooption(options, option, ap);
+ va_end(ap);
- options->colors = value;
- return 0;
-
- #endif /* ENABLE_COLORS */
-
- #if ENABLE_TIMESTAMP
-
- case EL_OPT_TS:
- VALID(EINVAL, 0 <= value && value <= EL_OPT_TS_OFF);
-
- options->timestamp = value;
- return 0;
-
- case EL_OPT_TS_TM:
- VALID(EINVAL, 0 <= value && value <= EL_OPT_TS_TM_MONOTONIC);
-
- options->timestamp_timer = value;
- return 0;
-
- #endif /* ENABLE_TIMESTAMP */
-
- #if ENABLE_FINFO
-
- case EL_OPT_FINFO:
- VALID(EINVAL, (value & ~1) == 0);
-
- options->finfo = value;
- return 0;
-
- #endif /* ENABLE_FINFO */
-
- default:
- /*
- * if we get here, user used option that was disabled during compilation
- * time and is not implemented
- */
-
- errno = ENOSYS;
- return -1;
- }
+ return rc;
}
-