head 1.25; access; symbols L2NGATE:1.10.0.2 START_MICHAEL:1.8 L2_INITIAL:1.1.1.1 OSSP:1.1.1; locks; strict; comment @ * @; 1.25 date 2001.09.12.10.32.03; author ms; state dead; branches; next 1.24; 1.24 date 2001.09.12.08.13.12; author thl; state Exp; branches; next 1.23; 1.23 date 2001.09.12.08.08.46; author thl; state Exp; branches; next 1.22; 1.22 date 2001.09.10.09.48.48; author thl; state dead; branches; next 1.21; 1.21 date 2001.09.09.15.57.10; author rse; state Exp; branches; next 1.20; 1.20 date 2001.09.06.14.37.53; author rse; state Exp; branches; next 1.19; 1.19 date 2001.09.06.11.56.15; author rse; state Exp; branches; next 1.18; 1.18 date 2001.09.05.13.32.04; author thl; state Exp; branches; next 1.17; 1.17 date 2001.09.05.07.41.18; author rse; state Exp; branches; next 1.16; 1.16 date 2001.09.04.19.18.49; author rse; state Exp; branches; next 1.15; 1.15 date 2001.09.04.15.41.17; author rse; state Exp; branches; next 1.14; 1.14 date 2001.09.04.14.56.25; author rse; state Exp; branches; next 1.13; 1.13 date 2001.09.04.13.52.59; author rse; state Exp; branches; next 1.12; 1.12 date 2001.09.03.13.43.33; author rse; state Exp; branches; next 1.11; 1.11 date 2001.09.03.12.16.44; author rse; state Exp; branches; next 1.10; 1.10 date 2001.09.02.13.18.36; author ms; state Exp; branches; next 1.9; 1.9 date 2001.08.26.13.01.45; author ms; state Exp; branches; next 1.8; 1.8 date 2001.08.15.10.36.03; author rse; state Exp; branches; next 1.7; 1.7 date 2001.05.26.08.04.12; author rse; state Exp; branches; next 1.6; 1.6 date 2001.05.26.08.02.55; author rse; state Exp; branches; next 1.5; 1.5 date 2001.05.24.09.40.28; author rse; state Exp; branches; next 1.4; 1.4 date 2001.05.22.18.47.31; author rse; state Exp; branches; next 1.3; 1.3 date 2001.05.19.20.08.30; author rse; state Exp; branches; next 1.2; 1.2 date 2001.05.11.17.07.52; author rse; state Exp; branches; next 1.1; 1.1 date 2001.05.10.19.46.01; author rse; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.05.10.19.46.01; author rse; state Exp; branches; next ; desc @@ 1.25 log @Source l2.h is now automatically generated by autoconf. Rerun ./configure to get a fresh l2.h revision, do not checkout from cvs! @ text @/* ** L2 - OSSP Logging Library ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP L2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/l2/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** l2.h: C API */ #ifndef __L2_H__ #define __L2_H__ /* version information (compile-time) */ #define L2_VERSION_STR "0.1.0 (08-Sep-2001)" #define L2_VERSION_HEX 0x001200 /* version information (run-time) */ typedef struct { const int v_hex; const char *v_short; const char *v_long; const char *v_tex; const char *v_gnu; const char *v_web; const char *v_sccs; const char *v_rcs; } l2_version_t; extern l2_version_t l2_version; /* include standard environment we are based on */ #include #include #include #include /* counterbalance poor standard environments */ #ifndef NULL #define NULL (void *)0 #endif #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif /* forward declarations for opaque data structures */ union l2_context_un; struct l2_param_st; struct l2_stream_st; struct l2_channel_st; struct l2_handler_st; /* corresponding data types for data structures */ typedef union l2_context_un l2_context_t; typedef struct l2_param_st l2_param_t; typedef struct l2_handler_st l2_handler_t; typedef struct l2_stream_st l2_stream_t; typedef struct l2_channel_st l2_channel_t; /* list of logging levels (high to low priority; low to high amount of logging) */ typedef enum { L2_LEVEL_NONE = 0, L2_LEVEL_PANIC = (1 << 0), L2_LEVEL_CRITICAL = (1 << 1), L2_LEVEL_ERROR = (1 << 2), L2_LEVEL_WARNING = (1 << 3), L2_LEVEL_NOTICE = (1 << 4), L2_LEVEL_INFO = (1 << 5), L2_LEVEL_TRACE = (1 << 6), L2_LEVEL_DEBUG = (1 << 7) } l2_level_t; #define L2_LEVEL_CUSTOM(n) (1 << (8+(n)) /* all levels from highest (PANIC) to and including a particular low level */ #define L2_LEVEL_UPTO(level) \ (((level)-1)|(level)) /* list of return values */ typedef enum { L2_OK, L2_ERR_ARG, /* invalid argument */ L2_ERR_USE, /* invalid usage */ L2_ERR_MEM, /* no more memory available */ L2_ERR_SYS, /* system error (see errno) */ L2_ERR_IO, /* input/output error */ L2_ERR_FMT, /* message formating error */ L2_ERR_INT /* internal error */ } l2_result_t; /* context union for storing data */ union l2_context_un { char c; short s; int i; long l; float f; double d; char *cp; void *vp; }; /* list of types for storing data */ typedef enum { L2_TYPE_CHAR, L2_TYPE_SHORT, L2_TYPE_INT, L2_TYPE_LONG, L2_TYPE_FLOAT, L2_TYPE_DOUBLE, L2_TYPE_STRING, L2_TYPE_CHARPTR, L2_TYPE_VOIDPTR } l2_type_t; /* parameter specification */ struct l2_param_st { char *name; l2_type_t type; void *store; }; /* parameter constructors */ #define L2_PARAM_SET(pa,n,t,s) \ pa.name = #n, pa.type = L2_TYPE_##t, pa.store = s #define L2_PARAM_END(pa) \ pa.name = NULL /* list of handler types */ typedef enum { L2_CHANNEL_FILTER, L2_CHANNEL_OUTPUT } l2_chtype_t; /* channel handler specification structure */ struct l2_handler_st { l2_chtype_t type; l2_result_t (*create) (l2_context_t *ctx, l2_channel_t *ch); l2_result_t (*configure)(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap); l2_result_t (*open) (l2_context_t *ctx, l2_channel_t *ch); l2_result_t (*write) (l2_context_t *ctx, l2_channel_t *ch, const char *buf, size_t bufsize); l2_result_t (*flush) (l2_context_t *ctx, l2_channel_t *ch); l2_result_t (*close) (l2_context_t *ctx, l2_channel_t *ch); l2_result_t (*destroy) (l2_context_t *ctx, l2_channel_t *ch); }; /* type of formatter callback function */ typedef l2_result_t (*l2_formatter_t)( l2_context_t *ctx, /* application context */ const char id, /* input arg: format string id ('x' of '%x') */ const char *param, /* input arg: format string parameter ('foo' of '%{foo}x') */ char *bufptr, /* input arg: pointer to output buffer */ size_t bufsize, /* input arg: maximum size of output buffer */ size_t *buflen, /* ouput arg: written characters in output buffer */ va_list *ap /* in/out arg: variable argument pointer */ ); /* list of shipped (output) channel handlers */ extern l2_handler_t l2_handler_null; extern l2_handler_t l2_handler_fd; extern l2_handler_t l2_handler_file; extern l2_handler_t l2_handler_pipe; extern l2_handler_t l2_handler_socket; extern l2_handler_t l2_handler_syslog; extern l2_handler_t l2_handler_smtp; /* list of shipped (filter) channel handlers */ extern l2_handler_t l2_handler_filter; extern l2_handler_t l2_handler_prefix; extern l2_handler_t l2_handler_buffer; /* channel operations */ l2_channel_t *l2_channel_create (l2_handler_t *h); l2_result_t l2_channel_configure (l2_channel_t *ch, const char *fmt, ...); l2_result_t l2_channel_open (l2_channel_t *ch); l2_result_t l2_channel_write (l2_channel_t *ch, const char *buf, size_t bufsize); l2_result_t l2_channel_flush (l2_channel_t *ch); l2_result_t l2_channel_close (l2_channel_t *ch); l2_result_t l2_channel_destroy (l2_channel_t *ch); l2_result_t l2_channel_stack (l2_channel_t *ch, l2_channel_t *chTop); l2_channel_t *l2_channel_downstream (l2_channel_t *ch); l2_chtype_t l2_channel_type (l2_channel_t *ch); /* stream operations */ l2_stream_t *l2_stream_create (void); l2_result_t l2_stream_channel (l2_stream_t *st, l2_channel_t *ch, unsigned int levelmask); l2_result_t l2_stream_formatter (l2_stream_t *st, char id, l2_formatter_t cb, l2_context_t *ctx); l2_result_t l2_stream_levels (l2_stream_t *st, unsigned int levelmask); l2_result_t l2_stream_log (l2_stream_t *st, unsigned int level, const char *fmt, ...); l2_result_t l2_stream_vlog (l2_stream_t *st, unsigned int level, const char *fmt, va_list ap); l2_result_t l2_stream_destroy (l2_stream_t *st); /* utility operations */ l2_result_t l2_util_setparams (l2_param_t p[], const char *fmt, va_list ap); l2_result_t l2_util_l2s (char *string, size_t maxlen, int sep, unsigned int levelmask); l2_result_t l2_util_s2l (const char *string, size_t maxlen, int sep, unsigned int *levelmask); l2_result_t l2_util_fmt_string (l2_context_t *, const char, const char *, char *, size_t, size_t *, va_list *); l2_result_t l2_util_fmt_dump (l2_context_t *, const char, const char *, char *, size_t, size_t *, va_list *); #endif /* __L2_H__ */ @ 1.24 log @added L2_LEVEL_NONE - 2nd attempt @ text @@ 1.23 log @added L2_LEVEL_NONE @ text @d83 1 @ 1.22 log @add version information to public API @ text @d33 17 @ 1.21 log @First cut for an SMTP output channel. This is very useful for (additionally) logging L2_LEVEL_PANIC messages in real-time to a mailbox via direct SMTP connection to a mail server. Internally it is very simple, because it is based on our new Socket Abstraction (SA) library (l2_ut_sa.[ch])... @ text @@ 1.20 log @Replace generic L2_ERROR with more granular L2_ERR_XXX and make sure that we always check with "!= L2_OK". @ text @d88 1 d167 1 @ 1.19 log @Add two cool extra formatter functions ;) l2_util_fmt_string: This can be used like %s, but instead of fetching only a "char *" from the var-args stack, it fetches a "char *" plus a "size_t" and this way allows one to log only a sub-string of a larger string without the need for any temporary buffers, etc. l2_util_fmt_dump: This can be used as "%{type}X" for dumping arbitrary octets. The parameter "type" can be either "text" (the default if only "%X" is used) for dumping the octets as text but with non-printable characters replaced by "\xXX" constructs; "hex" for dumping the octets in hexadecimal as "XX:XX:XX:XX" or "base64" for dumping the octets Base64 encoded. All three are intended for making it easier to produce reasonable L2_LEVEL_DEBUG messages without having to fiddle around with temporary buffers and having to care with non-printable characters. For instance, using... : l2_stream_formatter(st, 'D', l2_util_fmt_dump, NULL); : l2_stream_vlog(st, L2_LEVEL_DEBUG, "%{text}D %{hex}D %{base64}D\n", "foo", 12345, "foo\1bar", 7, "foo\1bar", 7, "foo\1bar", 7); : ...produces "foo\x01bar 66:6f:6f:01:62:61:72 Zm9vAWJhcg==" in the output. @ text @d84 6 a89 1 L2_ERROR @ 1.18 log @added to utility functions for transforming levelmask between string and int and vice versa @ text @a166 2 /* level operations */ d192 2 @ 1.17 log @Provide an L2_TYPE_STRING for the channel configuration steps. This is like L2_TYPE_CHARPTR but treats the target as a NUL-terminated string and performs a strdup() on it. This make the channels simpler, because they no longer have to post-process the configuration step in order to make own copies of provided strings. @ text @d75 1 d167 2 d191 3 a193 1 l2_result_t l2_util_setparams(l2_param_t p[], const char *fmt, va_list ap); @ 1.16 log @Be pedantically correct: handler hooks return "l2_result_t" and not "int", although currently it is just an int/enum. @ text @d106 1 @ 1.15 log @Revamp channel handler API: Instead of passing the downstream channel to all channels we instead provide a l2_channel_downstream() function and provide the current channel. This way the handler API is prototype-wise fully orthogonal with the channel API (which it implements) and we no longer pass information to 2/3 of our (output) channels which is of no use there. Additionally add a channel type field to l2_handler_t which allows a handler to say what type of channel it implements (filter or output). This information is now used in l2_channel_stack() to make sure that one can only stack a filter channel on top of another channel. For convinience reasons there is also a new l2_channel_type() function which allows one to query the type of a particular channel. @ text @d132 7 a138 7 int (*create) (l2_context_t *ctx, l2_channel_t *ch); int (*configure)(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap); int (*open) (l2_context_t *ctx, l2_channel_t *ch); int (*write) (l2_context_t *ctx, l2_channel_t *ch, const char *buf, size_t bufsize); int (*flush) (l2_context_t *ctx, l2_channel_t *ch); int (*close) (l2_context_t *ctx, l2_channel_t *ch); int (*destroy) (l2_context_t *ctx, l2_channel_t *ch); @ 1.14 log @cleanup level API (no need for retrieving old mask just in one function - either in all or in none). @ text @d123 6 d131 8 a138 7 int (*create) (l2_context_t *ctx); int (*configure)(l2_context_t *ctx, const char *fmt, va_list ap); int (*open) (l2_context_t *ctx, l2_channel_t *downstream); int (*write) (l2_context_t *ctx, l2_channel_t *downstream, const char *buf, size_t buf_size); int (*flush) (l2_context_t *ctx, l2_channel_t *downstream); int (*close) (l2_context_t *ctx, l2_channel_t *downstream); int (*destroy) (l2_context_t *ctx); d166 10 a175 8 l2_channel_t *l2_channel_create (l2_handler_t *h); l2_result_t l2_channel_configure(l2_channel_t *ch, const char *fmt, ...); l2_result_t l2_channel_open (l2_channel_t *ch); l2_result_t l2_channel_write (l2_channel_t *ch, const char *buf, size_t bufsize); l2_result_t l2_channel_flush (l2_channel_t *ch); l2_result_t l2_channel_close (l2_channel_t *ch); l2_result_t l2_channel_destroy (l2_channel_t *ch); l2_result_t l2_channel_stack (l2_channel_t *ch, l2_channel_t *chTop); d178 7 a184 7 l2_stream_t *l2_stream_create (void); l2_result_t l2_stream_channel (l2_stream_t *st, l2_channel_t *ch, unsigned int levelmask); l2_result_t l2_stream_formatter (l2_stream_t *st, char id, l2_formatter_t cb, l2_context_t *ctx); l2_result_t l2_stream_levels (l2_stream_t *st, unsigned int levelmask); l2_result_t l2_stream_log (l2_stream_t *st, unsigned int level, const char *fmt, ...); l2_result_t l2_stream_vlog (l2_stream_t *st, unsigned int level, const char *fmt, va_list ap); l2_result_t l2_stream_destroy (l2_stream_t *st); @ 1.13 log @Wohhooooo! Here comes the underlying message formatting support: 1. renamed l2_channel_setparam() to l2_util_setparam() because it is just a utility function and is not tied to any channel. 2. moved l2_util_setparam() to its own l2_ut_param.c source file. 3. added l2_ut_format.c which contains a slightly adjusted version of Str's str_format() stuff under the name l2_util_format(). 4. use l2_util_format() in l2_stream.c instead of vsnprintf() and this way finally support l2_formatter_t callbacks. 5. cleanup adjustments to the l2_stream_formatter() API. Let's rock... @ text @d172 3 a174 3 l2_result_t l2_stream_levels (l2_stream_t *st, unsigned int levelmask, unsigned int *levelmaskold); l2_result_t l2_stream_log (l2_stream_t *st, unsigned int log_level, const char *fmt, ...); l2_result_t l2_stream_vlog (l2_stream_t *st, unsigned int log_level, const char *fmt, va_list ap); @ 1.12 log @- replace "int" with "l2_result_t" in L2 channel API - use a 2^n for L2_LEVEL_XXX in order to be able to create mask - remember loglevel for each channel - rewrite test suite @ text @d135 8 a142 7 typedef int (*l2_formatter_t)( l2_context_t *context, const char *name, const char *param, char *buf, size_t bufsize, va_list ap a157 2 /* parameter operations */ a166 1 l2_result_t l2_channel_setparams(l2_param_t p[], const char *fmt, va_list ap); d171 1 a171 1 l2_result_t l2_stream_formatter (l2_stream_t *st, const char *name, l2_formatter_t cb, l2_context_t *ctx); d176 3 @ 1.11 log @revamped L2 stream API @ text @d64 1 a64 1 /* list of logging levels */ d66 8 a73 8 L2_LEVEL_DEBUG, L2_LEVEL_TRACE, L2_LEVEL_INFO, L2_LEVEL_NOTICE, L2_LEVEL_WARNING, L2_LEVEL_ERROR, L2_LEVEL_CRITICAL, L2_LEVEL_PANIC d76 4 d161 8 a168 8 int l2_channel_configure(l2_channel_t *ch, const char *fmt, ...); int l2_channel_open (l2_channel_t *ch); int l2_channel_write (l2_channel_t *ch, const char *buf, size_t bufsize); int l2_channel_flush (l2_channel_t *ch); int l2_channel_close (l2_channel_t *ch); int l2_channel_destroy (l2_channel_t *ch); l2_channel_t *l2_channel_stack (l2_channel_t *ch1, l2_channel_t *ch2); int l2_channel_setparams(l2_param_t p[], const char *fmt, va_list ap); @ 1.10 log @Revert to last version due to new design of l2_ch_socket_t. @ text @d168 6 a173 6 l2_stream_t *l2_stream_channel (l2_stream_t *st, l2_channel_t *ch, unsigned int levelmask); l2_stream_t *l2_stream_formatter (l2_stream_t *st, l2_formatter_t *cb, l2_context_t *ctx); unsigned int l2_stream_levels (l2_stream_t *st, unsigned int levelmask); void l2_stream_log (l2_stream_t *st, unsigned int log_level, const char *fmt, ...); void l2_stream_vlog (l2_stream_t *st, unsigned int log_level, const char *fmt, va_list ap); void l2_stream_destroy (l2_stream_t *st); @ 1.9 log @Added unsigned short type to PARAMETER macros for sockaddr_in struct. @ text @a97 1 L2_TYPE_USHORT, @ 1.8 log @Fix more ossp.com references by replacing with the correct domain name ossp.org. @ text @d98 1 @ 1.7 log @cleanup style @ text @d7 1 a7 1 ** can be found at http://www.ossp.com/pkg/l2/. @ 1.6 log @change terminology: below -> downstream @ text @d171 2 a172 2 void l2_stream_log (l2_stream_t *st, unsigned int log_level, const char* fmt, ...); void l2_stream_vlog (l2_stream_t *st, unsigned int log_level, const char* fmt, va_list ap); @ 1.5 log @o rename l2_error_t to l2_result_t o introduce internal channel state for API robustness @ text @d123 4 a126 4 int (*open) (l2_context_t *ctx, l2_channel_t *below); int (*write) (l2_context_t *ctx, l2_channel_t *below, const char *buf, size_t buf_size); int (*flush) (l2_context_t *ctx, l2_channel_t *below); int (*close) (l2_context_t *ctx, l2_channel_t *below); @ 1.4 log @Simplify things by merging the parameter stuff into l2_channel.c and the l2_stream_t related things into l2_stream.c @ text @d80 1 a80 1 } l2_error_t; @ 1.3 log @the "int l2_channel_configure(l2_channel_t *ch, const char *fmt, ...);" beast was my idea, so it is fair to also provide the necessary tool for implementing the underlying handler functions. Here it is, l2_param_parse(). @ text @a153 1 int l2_param_parse (l2_param_t p[], const char *fmt, va_list ap); a156 1 l2_channel_t *l2_channel_stack (l2_channel_t *ch1, l2_channel_t *ch2); d163 2 @ 1.2 log @Fill in channel handler template code. @ text @d33 2 d39 11 d52 1 d59 1 d82 1 a82 1 /* context union for callbacks */ d84 2 d90 1 a91 1 char *cp; d94 25 d152 3 @ 1.1 log @Initial revision @ text @d98 13 @ 1.1.1.1 log @L2 initial source tree @ text @@