head 1.27; access; symbols L2_0_9_13:1.27 FSL_1_7_0:1.27 L2_0_9_12:1.27 LMTP2NNTP_1_4_1:1.27 LMTP2NNTP_1_4_0:1.27 FSL_1_6_1:1.27 L2_0_9_11:1.27 FSL_1_6_0:1.26 FSL_1_6b2:1.26 L2_0_9_10:1.26 FSL_1_6b1:1.26 L2_0_9_9:1.26 LMTP2NNTP_1_3_0:1.25 LMTP2NNTP_1_3b2:1.25 LMTP2NNTP_1_3b1:1.25 LMTP2NNTP_1_3a3:1.25 FSL_1_5_0:1.25 LMTP2NNTP_1_3a2:1.25 FSL_1_5a3:1.25 LMTP2NNTP_1_3a1:1.25 FSL_1_5a2:1.25 L2_0_9_8:1.25 FSL_1_5a1:1.25 L2_0_9_7:1.25 L2_0_9_6:1.25 FSL_1_4_0:1.25 FSL_1_4b1:1.25 L2_0_9_5:1.25 FSL_1_4a1:1.25 FSL_1_3_0:1.25 FSL_1_3b1:1.25 L2_0_9_4:1.25 FSL_1_2_1:1.25 L2_0_9_3:1.25 FSL_1_2_0:1.23 L2_0_9_2:1.23 FSL_1_1_0:1.23 FSL_1_1b1:1.23 WORKOFF:1.23.0.2 WORKOFF_BP:1.23 FSL_1_0_8:1.23 LMTP2NNTP_1_2_0:1.23 LMTP2NNTP_1_2b4:1.23 LMTP2NNTP_1_2b3:1.23 LMTP2NNTP_1_2b2:1.23 LMTP2NNTP_1_2b1:1.23 LMTP2NNTP_1_2a8:1.23 LMTP2NNTP_1_2a7:1.23 FSL_1_0_7:1.23 FSL_1_0_6:1.22 FSL_1_0_5:1.22 FSL_1_0_4:1.22 L2_0_9_1:1.22 FSL_1_0_3:1.22 LMTP2NNTP_1_2a6:1.22 FSL_1_0_2:1.22 FSL_1_0_1:1.21 FSL_1_0_0:1.21 FSL_0_9_0:1.21 L2_0_9_0:1.21 FSL_0_1_12:1.20 FSL_0_1_11:1.20 FSL_0_1_10:1.20 FSL_0_1_9:1.20 FSL_0_1_8:1.20 FSL_0_1_7:1.20 FSL_0_1_6:1.20 FSL_0_1_5:1.20 FSL_0_1_1:1.19 LMTP2NNTP_1_2a5:1.19 LMTP2NNTP_1_2a4:1.19 LMTP2NNTP_1_2a3:1.19 LMTP2NNTP_1_2a1:1.18 LMTP2NNTP_1_1_1:1.15 LMTP2NNTP_1_1_0:1.15 LMTP2NNTP_1_1b4:1.15 LMTP2NNTP_1_1b3:1.15 L2_CHANNEL_ONLY_REVAMPING_BEFORE:1.15 LMTP2NNTP_1_1b2:1.15 LMTP2NNTP_1_1b1:1.15 L2_0_1_0:1.13 START_MICHAEL:1.4 L2_INITIAL:1.1.1.1 OSSP:1.1.1; locks; strict; comment @ * @; 1.27 date 2005.10.03.08.08.11; author rse; state Exp; branches; next 1.26; 1.26 date 2005.01.24.15.03.17; author rse; state Exp; branches; next 1.25; 1.25 date 2003.09.15.08.12.28; author thl; state Exp; branches; next 1.24; 1.24 date 2003.09.10.13.02.17; author rse; state Exp; branches; next 1.23; 1.23 date 2003.01.06.11.41.51; author rse; state Exp; branches; next 1.22; 1.22 date 2002.08.06.12.55.06; author thl; state Exp; branches; next 1.21; 1.21 date 2002.07.30.19.08.24; author rse; state Exp; branches; next 1.20; 1.20 date 2002.07.25.12.28.55; author rse; state Exp; branches; next 1.19; 1.19 date 2002.01.02.17.07.38; author rse; state Exp; branches; next 1.18; 1.18 date 2001.11.07.13.05.20; author rse; state Exp; branches; next 1.17; 1.17 date 2001.11.07.11.37.18; author rse; state Exp; branches; next 1.16; 1.16 date 2001.11.03.22.51.36; author rse; state Exp; branches; next 1.15; 1.15 date 2001.10.09.15.34.55; author rse; state Exp; branches; next 1.14; 1.14 date 2001.10.09.14.03.04; author ms; state Exp; branches; next 1.13; 1.13 date 2001.09.12.13.05.39; author rse; state Exp; branches; next 1.12; 1.12 date 2001.09.12.09.42.34; author ms; state Exp; branches; next 1.11; 1.11 date 2001.09.11.11.59.59; author rse; state Exp; branches; next 1.10; 1.10 date 2001.09.06.16.10.05; author rse; state Exp; branches; next 1.9; 1.9 date 2001.09.06.14.37.53; author rse; state Exp; branches; next 1.8; 1.8 date 2001.09.05.13.56.43; author rse; state Exp; branches; next 1.7; 1.7 date 2001.09.05.07.47.12; author rse; state Exp; branches; next 1.6; 1.6 date 2001.09.04.19.18.49; author rse; state Exp; branches; next 1.5; 1.5 date 2001.09.04.15.41.17; author rse; state Exp; branches; next 1.4; 1.4 date 2001.08.15.10.36.03; author rse; state Exp; branches; next 1.3; 1.3 date 2001.05.26.08.02.55; 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.27 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_ch_prefix.c: prefixing channel implementation */ #include #include #include #include #include "l2.h" #include "l2_p.h" /* declare private channel configuration */ typedef struct { char *prefix; char *timezone; } l2_ch_prefix_t; /* create channel */ static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_prefix_t *cfg; /* allocate private channel configuration */ if ((cfg = (l2_ch_prefix_t *)malloc(sizeof(l2_ch_prefix_t))) == NULL) return L2_ERR_MEM; /* initialize configuration with reasonable defaults */ cfg->prefix = NULL; cfg->timezone = strdup("local"); /* link private channel configuration into channel context */ ctx->vp = cfg; return L2_OK; } /* configure channel */ static l2_result_t hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap) { l2_ch_prefix_t *cfg = (l2_ch_prefix_t *)ctx->vp; l2_param_t pa[3]; l2_result_t rv; l2_env_t *env; /* feed and call generic parameter parsing engine */ L2_PARAM_SET(pa[0], prefix, STR, &cfg->prefix); L2_PARAM_SET(pa[1], timezone, STR, &cfg->timezone); L2_PARAM_END(pa[2]); l2_channel_env(ch, &env); rv = l2_util_setparams(env, pa, fmt, ap); /* argument consistency check */ if (rv == L2_OK) { if (cfg->timezone == NULL) return L2_ERR_ARG; if (!( strcmp(cfg->timezone, "local") == 0 || strcmp(cfg->timezone, "utc") == 0)) return L2_ERR_ARG; } return rv; } static l2_result_t expand_specials(char *buf, size_t bufsize, l2_level_t level) { char *cpSC; char *cpSE; char *cpBE; char caBuf[128]; size_t nBuf; l2_level_t rv; int bSubst; struct utsname uts; cpSC = buf; /* string current pointer */ cpSE = buf+strlen(buf); /* string end pointer */ cpBE = buf+bufsize; /* buffer end pointer */ while (cpSC < cpSE) { if ((cpSC+1) < cpSE && *cpSC == '%') { bSubst = FALSE; switch (*(cpSC+1)) { case 'L': { if ((rv = l2_util_l2s(caBuf, sizeof(caBuf), '\0', level)) != L2_OK) return rv; bSubst = TRUE; break; } case 'N': { if (uname(&uts) != -1) l2_util_sprintf(caBuf, sizeof(caBuf), uts.nodename); else l2_util_sprintf(caBuf, sizeof(caBuf), "localhost"); bSubst = TRUE; break; } case 'P': { l2_util_sprintf(caBuf, sizeof(caBuf), "%lu", (unsigned long)getpid()); bSubst = TRUE; break; } } if (bSubst) { nBuf = strlen(caBuf); if ((cpBE-cpSE)+2 < nBuf) return L2_ERR_MEM; memmove(cpSC+nBuf, cpSC+2, cpSE-(cpSC+2)+1); memmove(cpSC, caBuf, nBuf); cpSC += nBuf; cpSE += (-2+nBuf); continue; } } cpSC++; } return L2_OK; } /* write to channel */ static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, l2_level_t level, const char *buf, size_t buf_size) { l2_ch_prefix_t *cfg = (l2_ch_prefix_t *)ctx->vp; l2_channel_t *downstream; time_t t; struct tm *tm; size_t n; l2_result_t rv; char buf1[1024]; char buf2[1024]; /* optionally provide prefix */ if (cfg->prefix != NULL) { if (strlen(cfg->prefix) >= sizeof(buf1)) return L2_ERR_MEM; strcpy(buf1, cfg->prefix); if ((rv = expand_specials(buf1, sizeof(buf1), level)) != L2_OK) return rv; t = time(NULL); if (strcmp(cfg->timezone, "local") == 0) tm = localtime(&t); else if (strcmp(cfg->timezone, "utc") == 0) tm = gmtime(&t); else return L2_ERR_ARG; if ((n = strftime(buf2, sizeof(buf2), buf1, tm)) == 0) return L2_ERR_SYS; n += l2_util_sprintf(buf2+n, sizeof(buf2)-n, "%s", buf); downstream = NULL; while ((rv = l2_channel_downstream(ch, &downstream)) == L2_OK) if ((rv = l2_channel_write(downstream, level, buf2, n)) != L2_OK) return rv; return L2_OK; } return L2_OK_PASS; } /* destroy channel */ static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_prefix_t *cfg = (l2_ch_prefix_t *)ctx->vp; /* free prefix structure */ if (cfg->prefix != NULL) free(cfg->prefix); if (cfg->timezone != NULL) free(cfg->timezone); free(cfg); return L2_OK_PASS; } /* exported channel handler structure */ l2_handler_t l2_handler_prefix = { "prefix", L2_CHANNEL_FILTER, hook_create, hook_configure, NULL, hook_write, NULL, NULL, hook_destroy }; @ 1.26 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.25 log @fix function name @ 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.24 log @make sure we do atomic downstream writes for now @ text @d175 1 a175 1 n += l2_ut_sprintf(buf2+n, sizeof(buf2)-n, "%s", buf); @ 1.23 log @- remove trailing whitespaces - adjust copyright messages - consistently use "OSSP l2" - consistently talk about "Flexible Logging" - use standard OSSP ASCII-art @ text @d175 1 d180 1 @ 1.22 log @fixed %N on solaris "... successful ... non-negative ... Otherwise, -1 ..." @ 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 d68 1 a68 1 l2_param_t pa[3]; d83 1 a83 1 if (!( strcmp(cfg->timezone, "local") == 0 @ 1.21 log @polish for release @ text @d115 1 a115 1 if (uname(&uts) == 0) @ 1.20 log @add support for hostname/nodename expansion via %N @ text @d2 1 a2 1 ** L2 - OSSP Logging Library d7 1 a7 1 ** can be found at http://www.ossp.org/pkg/l2/. @ 1.19 log @bump copyright year @ text @d33 1 d36 1 d99 1 d114 8 d123 1 a123 1 sprintf(caBuf, "%lu", (unsigned long)getpid()); @ 1.18 log @Hell, I've seldom seen that it is needed to prepare and adjust such a lot of subtle details of existing code in order to make a new feature implementable in a straight-forward way. Anyway, here comes one more preparation change for the forthcoming channel tree specification parser: - change l2_util_setparam() to take an l2_env_t parameter which allows the function to report better error messages. - completely rewrite l2_util_setparam() to support calls l2_channel_configure(ch, "n1=v1,n2=v2,n3=v3") and/or l2_channel_configure(ch, "n1=%x,n2=%x,n3=%x", v1, v2, v3) instead of l2_channel_configure(ch, "n1,n2,n3", v1, v2, v3) This is both a step forward to make the interface of l2_channel_configure() more flexible (because one now can directly inline values instead of having them to be passed explicitly) and allows the spec parser not having to know the type (integer, floating point or string) of a parameter (which is important if one wants the parser to be independent of the implementing channel handlers). @ 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.17 log @More preparations for forthcoming channel tree specification parser (especially to allow the parser to determine the handler structure from a handler name without introducing another and this way redundant sub-API): - add "char *name" to l2_handler_t in order to tag each handler structure with the corresponding channel name - add l2_env_handler() function to add handler to l2_env_t objects. All l2_handler_xxxx are automatically pre-configured there after l2_env_create(). - change l2_channel_create() to take a "const char *name" (handler name) instead of the "l2_handler_t *h" (handler pointer) to make the stuff consistent and more clear. - adjust l2_test.c to reflect the changes. @ text @d67 1 d70 2 a71 2 L2_PARAM_SET(pa[0], prefix, STRING, &cfg->prefix); L2_PARAM_SET(pa[1], timezone, STRING, &cfg->timezone); d73 2 a74 1 rv = l2_util_setparams(pa, fmt, ap); @ 1.16 log @Channel-Only Revamping Step 1: allow multiple downstream channels in order to approach the later tree-like channel-only structure. @ text @d187 1 @ 1.15 log @Veto: back-out latest level-related changes. Sorry, Michael, the padding has to be done in l2_ch_prefix.c only. @ text @d137 1 a137 1 l2_channel_t *downstream = l2_channel_downstream(ch); d161 4 a164 2 if ((rv = l2_channel_write(downstream, level, buf2, n)) != L2_OK) return rv; d167 1 a167 5 /* write to downstream channel */ if ((rv = l2_channel_write(downstream, level, buf, buf_size)) != L2_OK) return rv; return L2_OK; a173 2 l2_channel_t *downstream = l2_channel_downstream(ch); l2_result_t rv; d182 1 a182 5 /* optionally destroy downstream channel, too */ if ((rv = l2_channel_destroy(downstream)) != L2_OK) return rv; return L2_OK; @ 1.14 log @Corrected prefix functionality, because channel write operations do not take level masks as input. @ text @d104 1 a104 1 if ((rv = l2_util_l2s(caBuf, sizeof(caBuf), level)) != L2_OK) @ 1.13 log @add support for %L (level) and %P (pid) to prefix channel @ text @d104 1 a104 1 if ((rv = l2_util_l2s(caBuf, sizeof(caBuf), '\0', level)) != L2_OK) @ 1.12 log @Upgraded both stream and channel-level APIs to include new L2_LEVEL parameter design. @ text @d31 2 d38 1 a38 1 char *timefmt; a39 1 char timebuf[1024]; d52 1 a52 1 cfg->timefmt = NULL; d69 1 a69 1 L2_PARAM_SET(pa[0], timefmt, STRING, &cfg->timefmt); d86 46 d142 2 d146 6 a151 1 if (cfg->timefmt != NULL) { d159 1 a159 1 if ((n = strftime(cfg->timebuf, sizeof(cfg->timebuf), cfg->timefmt, tm)) == 0) d161 1 a161 1 if ((rv = l2_channel_write(downstream, level, cfg->timebuf, n)) != L2_OK) d180 2 a181 2 if (cfg->timefmt != NULL) free(cfg->timefmt); @ 1.11 log @fix channel destruction in case of channel stacks @ text @d86 2 a87 2 static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, const char *buf, size_t buf_size) d107 1 a107 1 if ((rv = l2_channel_write(downstream, cfg->timebuf, n)) != L2_OK) d112 1 a112 1 if ((rv = l2_channel_write(downstream, buf, buf_size)) != L2_OK) @ 1.10 log @Simplify channels again: The channel framework gurranties that the handler context is available if the handler has set it, so there is no need to perform an additional run-time check and try to return L2_ERR_ARG. @ text @d122 2 d131 4 @ 1.9 log @Replace generic L2_ERROR with more granular L2_ERR_XXX and make sure that we always check with "!= L2_OK". @ text @d89 2 a90 2 l2_ch_prefix_t *cfg; l2_channel_t *downstream; a95 4 /* get environment */ cfg = (l2_ch_prefix_t *)ctx->vp; downstream = l2_channel_downstream(ch); d123 1 a128 1 ctx->vp = NULL; @ 1.8 log @Implemented prefix channel plus mini test. @ text @d48 1 a48 1 return L2_ERROR; d76 1 a76 1 return L2_ERROR; d79 1 a79 1 return L2_ERROR; d108 1 a108 1 return L2_ERROR; d110 1 a110 1 return L2_ERROR; @ 1.7 log @Be politically correct: channels are intended to be implemented also by users, which have only access to the public API (l2.h), so do not even try to use anything more in our own shipped channels. @ text @d30 2 d34 8 d44 13 d60 1 d63 18 a80 2 return L2_OK; } d82 1 a82 3 static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch) { return L2_OK; d85 1 d87 1 a87 1 const char *buf, size_t buf_size) d89 30 d122 2 a123 1 static l2_result_t hook_flush(l2_context_t *ctx, l2_channel_t *ch) d125 1 a125 2 return L2_OK; } d127 6 a132 4 static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch) { return L2_OK; } a133 2 static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch) { d137 1 d142 1 a142 1 hook_open, d144 2 a145 2 hook_flush, hook_close, @ 1.6 log @Be pedantically correct: handler hooks return "l2_result_t" and not "int", although currently it is just an int/enum. @ text @a30 1 #include "l2_p.h" @ 1.5 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 @d33 1 a33 1 static int hook_create(l2_context_t *ctx, l2_channel_t *ch) d38 1 a38 1 static int hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap) d43 1 a43 1 static int hook_open(l2_context_t *ctx, l2_channel_t *ch) d48 1 a48 1 static int hook_write(l2_context_t *ctx, l2_channel_t *ch, d54 1 a54 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *ch) d59 1 a59 1 static int hook_close(l2_context_t *ctx, l2_channel_t *ch) d64 1 a64 1 static int hook_destroy(l2_context_t *ctx, l2_channel_t *ch) @ 1.4 log @Fix more ossp.com references by replacing with the correct domain name ossp.org. @ text @d33 1 a33 1 static int hook_create(l2_context_t *ctx) d38 1 a38 1 static int hook_configure(l2_context_t *ctx, const char *fmt, va_list ap) d43 1 a43 1 static int hook_open(l2_context_t *ctx, l2_channel_t *downstream) d48 1 a48 1 static int hook_write(l2_context_t *ctx, l2_channel_t *downstream, d54 1 a54 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *downstream) d59 1 a59 1 static int hook_close(l2_context_t *ctx, l2_channel_t *downstream) d64 1 a64 1 static int hook_destroy(l2_context_t *ctx) d70 1 @ 1.3 log @change terminology: below -> downstream @ text @d7 1 a7 1 ** can be found at http://www.ossp.com/pkg/l2/. @ 1.2 log @Fill in channel handler template code. @ text @d43 1 a43 1 static int hook_open(l2_context_t *ctx, l2_channel_t *below) d48 1 a48 1 static int hook_write(l2_context_t *ctx, l2_channel_t *below, d54 1 a54 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *below) d59 1 a59 1 static int hook_close(l2_context_t *ctx, l2_channel_t *below) @ 1.1 log @Initial revision @ text @d33 46 @ 1.1.1.1 log @L2 initial source tree @ text @@