diff options
author | Michał Łyszczek <michal.lyszczek@bofc.pl> | 2017-08-13 20:32:32 +0200 |
---|---|---|
committer | Michał Łyszczek <michal.lyszczek@bofc.pl> | 2017-08-13 20:32:32 +0200 |
commit | 335c2197c16b1d36d3549c9614b52df5c2545397 (patch) | |
tree | b9b706d85d6d7356e95c0c9cd4af6258c49b8623 | |
parent | fac685704ed47e391c038ecc25eb1a46ab1069aa (diff) | |
download | embedlog-335c2197c16b1d36d3549c9614b52df5c2545397.tar.gz embedlog-335c2197c16b1d36d3549c9614b52df5c2545397.tar.bz2 embedlog-335c2197c16b1d36d3549c9614b52df5c2545397.zip |
Added feature to print log to file
-rw-r--r-- | configure.ac | 45 | ||||
-rw-r--r-- | include/embedlog.h | 30 | ||||
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/el-file.c | 403 | ||||
-rw-r--r-- | src/el-file.h | 15 | ||||
-rw-r--r-- | src/el-puts.c | 9 | ||||
-rw-r--r-- | src/options.c | 230 |
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; } - |