head 1.12; access; symbols L2_0_9_13:1.12 FSL_1_7_0:1.12 L2_0_9_12:1.12 LMTP2NNTP_1_4_1:1.12 LMTP2NNTP_1_4_0:1.12 FSL_1_6_1:1.12 L2_0_9_11:1.12 FSL_1_6_0:1.11 FSL_1_6b2:1.11 L2_0_9_10:1.11 FSL_1_6b1:1.11 L2_0_9_9:1.11 LMTP2NNTP_1_3_0:1.10 LMTP2NNTP_1_3b2:1.10 LMTP2NNTP_1_3b1:1.10 LMTP2NNTP_1_3a3:1.10 FSL_1_5_0:1.10 LMTP2NNTP_1_3a2:1.10 FSL_1_5a3:1.10 LMTP2NNTP_1_3a1:1.10 FSL_1_5a2:1.10 L2_0_9_8:1.10 FSL_1_5a1:1.10 L2_0_9_7:1.10 L2_0_9_6:1.10 FSL_1_4_0:1.10 FSL_1_4b1:1.10 L2_0_9_5:1.10 FSL_1_4a1:1.10 FSL_1_3_0:1.10 FSL_1_3b1:1.10 L2_0_9_4:1.10 FSL_1_2_1:1.10 L2_0_9_3:1.10 FSL_1_2_0:1.10 L2_0_9_2:1.10 FSL_1_1_0:1.10 FSL_1_1b1:1.10 WORKOFF:1.10.0.2 WORKOFF_BP:1.10 FSL_1_0_8:1.10 LMTP2NNTP_1_2_0:1.10 LMTP2NNTP_1_2b4:1.10 LMTP2NNTP_1_2b3:1.10 LMTP2NNTP_1_2b2:1.10 LMTP2NNTP_1_2b1:1.10 LMTP2NNTP_1_2a8:1.10 LMTP2NNTP_1_2a7:1.10 FSL_1_0_7:1.10 FSL_1_0_6:1.9 FSL_1_0_5:1.9 FSL_1_0_4:1.9 L2_0_9_1:1.9 FSL_1_0_3:1.9 LMTP2NNTP_1_2a6:1.9 FSL_1_0_2:1.9 FSL_1_0_1:1.9 FSL_1_0_0:1.9 FSL_0_9_0:1.9 L2_0_9_0:1.9 FSL_0_1_12:1.8 FSL_0_1_11:1.8 FSL_0_1_10:1.8 FSL_0_1_9:1.8 FSL_0_1_8:1.8 FSL_0_1_7:1.8 FSL_0_1_6:1.8 FSL_0_1_5:1.8 FSL_0_1_1:1.8 LMTP2NNTP_1_2a5:1.8 LMTP2NNTP_1_2a4:1.8 LMTP2NNTP_1_2a3:1.8 LMTP2NNTP_1_2a1:1.4; locks; strict; comment @ * @; 1.12 date 2005.10.03.08.08.11; author rse; state Exp; branches; next 1.11; 1.11 date 2005.01.24.15.03.17; author rse; state Exp; branches; next 1.10; 1.10 date 2003.01.06.11.41.52; author rse; state Exp; branches; next 1.9; 1.9 date 2002.07.30.19.08.25; author rse; state Exp; branches; next 1.8; 1.8 date 2002.01.02.17.07.38; author rse; state Exp; branches; next 1.7; 1.7 date 2001.12.22.22.18.34; author rse; state Exp; branches; next 1.6; 1.6 date 2001.12.22.22.04.18; author rse; state Exp; branches; next 1.5; 1.5 date 2001.12.14.12.42.07; author rse; state Exp; branches; next 1.4; 1.4 date 2001.11.30.09.44.47; author rse; state Exp; branches; next 1.3; 1.3 date 2001.11.07.16.43.07; author rse; state Exp; branches; next 1.2; 1.2 date 2001.11.07.16.35.18; author rse; state Exp; branches; next 1.1; 1.1 date 2001.11.07.16.17.09; author rse; state Exp; branches; next ; desc @@ 1.12 log @Adjust copyright messages for new year 2005. @ text @/* ** OSSP l2 - Flexible Logging ** Copyright (c) 2001-2005 Cable & Wireless ** Copyright (c) 2001-2005 The OSSP Project ** Copyright (c) 2001-2005 Ralf S. Engelschall ** ** This file is part of OSSP l2, a flexible logging library which ** can be found at http://www.ossp.org/pkg/lib/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_spec.c: channel tree specification support */ #include "l2.h" #include "l2_p.h" #include "l2_spec.h" /* prototypes for Flex-generated scanner */ extern int l2_spec_lex_init(void *); extern int l2_spec_lex_destroy(void *); extern void l2_spec_set_extra(void *, void *); /* prototypes for Bison-generated parser */ extern int l2_spec_parse(void *); /* build a channel tree according to a textual specification */ l2_result_t l2_spec(l2_channel_t **ch, l2_env_t *env, const char *spec, ...) { va_list ap; l2_result_t rv; /* pass-through to va_list-based variant */ va_start(ap, spec); rv = l2_vspec(ch, env, spec, ap); va_end(ap); return rv; } /* build a channel tree according to a textual specification (va_list variant) */ l2_result_t l2_vspec(l2_channel_t **ch, l2_env_t *env, const char *spec, va_list ap) { l2_spec_ctx_t ctx; void *yyscan; char *specstr; /* on-the-fly create or take over specification string */ if ((specstr = l2_util_vasprintf(spec, ap)) == NULL) return L2_ERR_ARG; /* initialize scanner */ l2_spec_lex_init(&yyscan); l2_spec_set_extra(&ctx, yyscan); /* establish our own context which is passed through the parser and scanner */ ctx.yyscan = yyscan; ctx.inputptr = specstr; ctx.inputbuf = specstr; ctx.inputlen = strlen(specstr); ctx.env = env; ctx.ch = NULL; ctx.chTmp = NULL; ctx.rv = L2_OK; /* start the parser loop */ if (l2_spec_parse(&ctx)) ctx.rv = (ctx.rv == L2_OK ? L2_ERR_INT : ctx.rv); /* destroy scanner */ l2_spec_lex_destroy(yyscan); /* destroy specification string */ free(specstr); /* provide root/top-level channel as result */ *ch = ctx.ch; return ctx.rv; } /* remember a specification parsing error (used internally) */ void l2_spec_error(l2_spec_ctx_t *ctx, l2_result_t rv, YYLTYPE *loc, const char *fmt, ...) { va_list ap; const char *cpF, *cpL; const char *cpP, *cpE; int line, column; char *cpBuf; char *cp; int n; /* determine first and last positions of token */ cpF = ctx->inputbuf+loc->first; cpL = ctx->inputbuf+loc->last; /* determine epilog and prolog of token */ cpP = cpF-4; if (cpP < ctx->inputbuf) cpP = ctx->inputbuf; cpE = cpL+4; if (cpE > ctx->inputbuf+ctx->inputlen) cpE = ctx->inputbuf+ctx->inputlen; /* calculate line and column of token */ line = 1; column = 1; for (cp = (char *)ctx->inputbuf; cp < (ctx->inputbuf+ctx->inputlen) && cp != cpF; cp++) { column++; if (*cp == '\n') { column = 1; line++; } } /* extract token context with mark token borders */ if ((cpBuf = malloc((cpE-cpP)+2+1)) == NULL) return; cp = cpBuf; n = cpF-cpP; memcpy(cp, cpP, n); cp += n; *cp++ = '<'; n = cpL-cpF; memcpy(cp, cpF, n); cp += n; *cp++ = '>'; n = cpE-cpL; memcpy(cp, cpL, n); cp += n; *cp++ = '\0'; /* remember error */ va_start(ap, fmt); if ((cp = l2_util_vasprintf(fmt, ap)) != NULL) { l2_env_errorinfo(ctx->env, rv, "line %d, column %d: `%s'; %s", line, column, cpBuf, cp); free(cp); } else l2_env_errorinfo(ctx->env, rv, "line %d, column %d: `%s'; N.A.", line, column, cpBuf); va_end(ap); ctx->rv = rv; /* cleanup */ free(cpBuf); return; } @ 1.11 log @Adjust copyright messages for new year 2005. @ text @d3 3 a5 3 ** Copyright (c) 2001-2004 Cable & Wireless ** Copyright (c) 2001-2004 The OSSP Project ** Copyright (c) 2001-2004 Ralf S. Engelschall @ 1.10 log @- remove trailing whitespaces - adjust copyright messages - consistently use "OSSP l2" - consistently talk about "Flexible Logging" - use standard OSSP ASCII-art @ text @d3 3 a5 3 ** Copyright (c) 2001-2003 Cable & Wireless Deutschland GmbH ** Copyright (c) 2001-2003 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2003 Ralf S. Engelschall @ 1.9 log @polish for release @ text @d2 4 a5 3 ** OSSP l2 - Logging Library ** Copyright (c) 2001-2002 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) d7 1 a7 1 ** This file is part of OSSP L2, a flexible logging library which d72 1 a72 1 /* establish our own context which is passed @ 1.8 log @bump copyright year @ text @d2 1 a2 1 ** L2 - OSSP Logging Library d7 1 a7 1 ** can be found at http://www.ossp.org/pkg/l2/. @ 1.7 log @Fix l2_spec_error function and remove again the not really needed l2_env_verrorinfo function. @ text @d3 2 a4 2 ** Copyright (c) 2001 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001 Cable & Wireless Deutschland (http://www.cw.com/de/) @ 1.6 log @remove warning @ text @d101 1 d147 10 a156 2 l2_env_errorinfo(ctx->env, rv, "line %d, column %d: `%s'; %s", line, column, cpBuf, fmt); @ 1.5 log @Whoohooo! Add support for location tracking. This way the reported errors contain line, column, context and found/expected information. Now the specification parser is full featured... @ text @d123 1 a123 1 for (cp = ctx->inputbuf; cp < (ctx->inputbuf+ctx->inputlen) && cp != cpF; cp++) { @ 1.4 log @Allow a channel tree specification to be a printf-style string to make the API more powerful and to remove the burden from the application to pre-format the specification in an own buffer. @ text @d98 58 @ 1.3 log @reduce includes @ text @d43 15 a57 1 l2_result_t l2_spec(l2_channel_t **ch, l2_env_t *env, const char *spec) d61 5 d74 3 a76 3 ctx.inputptr = spec; ctx.inputbuf = spec; ctx.inputlen = strlen(spec); d88 3 @ 1.2 log @cleanup and documentation @ text @a32 1 #include "l2_spec_parse.h" @ 1.1 log @HEADS UP, guys: Here comes the first cut for the long-awaited channel tree specification parser and channel tree builder. This certainly makes L2 finally _THE_ killer library in the logging field. Woohooo... and the crowd goes wild! It allows one to build an arbitrary complex logging channel tree out of a single textual specification. An example follows: noop -> { prefix(prefix="[%d-%m-%Y/%H:%M:%S] %L test[%P]: ", timezone="local") -> filter(regex="hecking", negate="0") -> buffer(size="800") -> file(path="l2_test.log",append="1",perm="420"); error: syslog(ident="L2-Test", facility="user", remotehost="en1", logpid="1", target="remote"); panic: smtp(rcpt="rse@@engelschall.com", host="en1", port="25" } This allows one to log nice timestamp-prefixed messages containing the word "hecking" to a buffered file. Additionally if the message has a level higher or equal to "error" it also logs it remotely via UDP to the syslogd on en1. And additionally if the message is a panic message, it is also sent out as an Email via SMTP to the MTA on en1. Ever thought a C library has to be dull and simple? ;) PS: This stuff certainly needs more polishing and cleanup and also a few things I'll enhance in the future (for instance to remove the restriction that parameter values have to be in quotation marks, etc.). @ text @d1 28 a28 2 #include d35 1 a38 5 extern int l2_spec_debug; void dump(int level, l2_channel_t *ch) { l2_channel_t *chD; d40 2 a41 6 fprintf(stderr, "%*s%s (0x%lx)\n", level*4, "", ch->handler.name, ch); chD = NULL; while ((l2_channel_downstream(ch, &chD)) == L2_OK) dump(level+1, chD); return; } d43 1 d49 1 d53 2 d64 1 a64 3 #if 0 l2_spec_debug = 1; #endif d68 4 a72 4 dump(0, ctx.ch); l2_spec_lex_destroy(yyscan); @