head 1.34; access; symbols L2_0_9_13:1.34 FSL_1_7_0:1.34 L2_0_9_12:1.34 LMTP2NNTP_1_4_1:1.33 LMTP2NNTP_1_4_0:1.33 FSL_1_6_1:1.33 L2_0_9_11:1.33 FSL_1_6_0:1.32 FSL_1_6b2:1.32 L2_0_9_10:1.32 FSL_1_6b1:1.32 L2_0_9_9:1.32 LMTP2NNTP_1_3_0:1.31 LMTP2NNTP_1_3b2:1.31 LMTP2NNTP_1_3b1:1.31 LMTP2NNTP_1_3a3:1.31 FSL_1_5_0:1.31 LMTP2NNTP_1_3a2:1.31 FSL_1_5a3:1.31 LMTP2NNTP_1_3a1:1.31 FSL_1_5a2:1.31 L2_0_9_8:1.31 FSL_1_5a1:1.31 L2_0_9_7:1.31 L2_0_9_6:1.31 FSL_1_4_0:1.31 FSL_1_4b1:1.31 L2_0_9_5:1.31 FSL_1_4a1:1.31 FSL_1_3_0:1.31 FSL_1_3b1:1.31 L2_0_9_4:1.31 FSL_1_2_1:1.28 L2_0_9_3:1.28 FSL_1_2_0:1.28 L2_0_9_2:1.28 FSL_1_1_0:1.25 FSL_1_1b1:1.25 WORKOFF:1.25.0.2 WORKOFF_BP:1.25 FSL_1_0_8:1.25 LMTP2NNTP_1_2_0:1.25 LMTP2NNTP_1_2b4:1.25 LMTP2NNTP_1_2b3:1.25 LMTP2NNTP_1_2b2:1.25 LMTP2NNTP_1_2b1:1.25 LMTP2NNTP_1_2a8:1.25 LMTP2NNTP_1_2a7:1.25 FSL_1_0_7:1.25 FSL_1_0_6:1.24 FSL_1_0_5:1.24 FSL_1_0_4:1.24 L2_0_9_1:1.24 FSL_1_0_3:1.24 LMTP2NNTP_1_2a6:1.24 FSL_1_0_2:1.24 FSL_1_0_1:1.24 FSL_1_0_0:1.24 FSL_0_9_0:1.24 L2_0_9_0:1.24 FSL_0_1_12:1.23 FSL_0_1_11:1.23 FSL_0_1_10:1.22 FSL_0_1_9:1.22 FSL_0_1_8:1.22 FSL_0_1_7:1.22 FSL_0_1_6:1.22 FSL_0_1_5:1.22 FSL_0_1_1:1.22 LMTP2NNTP_1_2a5:1.22 LMTP2NNTP_1_2a4:1.22 LMTP2NNTP_1_2a3:1.21 LMTP2NNTP_1_2a1:1.20 LMTP2NNTP_1_1_1:1.17 LMTP2NNTP_1_1_0:1.17 LMTP2NNTP_1_1b4:1.17 LMTP2NNTP_1_1b3:1.17 L2_CHANNEL_ONLY_REVAMPING_BEFORE:1.17 LMTP2NNTP_1_1b2:1.17 LMTP2NNTP_1_1b1:1.17 L2_0_1_0:1.17 L2NGATE:1.7.0.2 START_MICHAEL:1.7 L2_INITIAL:1.1.1.1 OSSP:1.1.1; locks; strict; comment @ * @; 1.34 date 2007.03.02.15.13.28; author thl; state Exp; branches; next 1.33; commitid Z5uL2vuD8F2LJw8s; 1.33 date 2005.10.03.08.08.11; author rse; state Exp; branches; next 1.32; 1.32 date 2005.01.24.15.03.17; author rse; state Exp; branches; next 1.31; 1.31 date 2003.09.25.13.22.32; author thl; state Exp; branches; next 1.30; 1.30 date 2003.09.25.13.20.34; author thl; state Exp; branches; next 1.29; 1.29 date 2003.09.25.13.15.24; author thl; state Exp; branches; next 1.28; 1.28 date 2003.06.30.12.54.06; author thl; state Exp; branches; next 1.27; 1.27 date 2003.06.30.12.38.17; author thl; state Exp; branches; next 1.26; 1.26 date 2003.06.30.11.13.08; author thl; state Exp; branches; next 1.25; 1.25 date 2003.01.06.11.41.51; author rse; state Exp; branches; next 1.24; 1.24 date 2002.07.30.19.08.24; author rse; state Exp; branches; next 1.23; 1.23 date 2002.07.29.17.42.25; author rse; state Exp; branches; next 1.22; 1.22 date 2002.03.13.14.49.39; author thl; state Exp; branches; next 1.21; 1.21 date 2002.01.02.17.07.38; author rse; state Exp; branches; next 1.20; 1.20 date 2001.11.15.11.03.15; author ms; state Exp; branches; next 1.19; 1.19 date 2001.11.07.13.05.20; author rse; state Exp; branches; next 1.18; 1.18 date 2001.11.07.11.37.18; author rse; state Exp; branches; next 1.17; 1.17 date 2001.09.12.09.42.34; author ms; state Exp; branches; next 1.16; 1.16 date 2001.09.06.16.10.05; author rse; state Exp; branches; next 1.15; 1.15 date 2001.09.06.14.43.25; author rse; state Exp; branches; next 1.14; 1.14 date 2001.09.06.14.37.53; author rse; state Exp; branches; next 1.13; 1.13 date 2001.09.05.07.47.12; author rse; state Exp; branches; next 1.12; 1.12 date 2001.09.04.19.18.49; author rse; state Exp; branches; next 1.11; 1.11 date 2001.09.04.15.44.48; author rse; state Exp; branches; next 1.10; 1.10 date 2001.09.04.15.41.17; author rse; state Exp; branches; next 1.9; 1.9 date 2001.09.04.13.52.59; author rse; state Exp; branches; next 1.8; 1.8 date 2001.09.03.13.37.00; author rse; state Exp; branches; next 1.7; 1.7 date 2001.08.15.10.36.03; author rse; state Exp; branches; next 1.6; 1.6 date 2001.05.24.09.40.28; author rse; state Exp; branches; next 1.5; 1.5 date 2001.05.22.18.47.31; author rse; state Exp; branches; next 1.4; 1.4 date 2001.05.21.20.15.11; author rse; state Exp; branches; next 1.3; 1.3 date 2001.05.19.20.14.15; 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.34 log @large file support for l2_ch_file, motivated by the Kolab-Konsortium @ 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_file.c: file channel implementation */ #include "l2.h" #include #include #include #include #include #include /* declare private channel configuration */ typedef struct { int fd; char *path; int append; int trunc; int perm; int jitter; int jittercount; int monitor; long monitortime; dev_t monitordev; ino_t monitorino; } l2_ch_file_t; /* open channel file */ static void openchfile(l2_context_t *ctx, l2_channel_t *ch, int mode) { l2_ch_file_t *cfg = (l2_ch_file_t *)ctx->vp; mode_t mask; struct timeval tv; struct stat st; #ifdef O_LARGEFILE /* Support for 1996-03-20 addition to Single UNIX Specification for * systems that still require the Transitional Extensions to System * Interfaces to support arbitrary file sizes (LFS >2GiB) */ mode |= O_LARGEFILE; #endif /* open channel file */ mask = umask(0); cfg->fd = open(cfg->path, mode, cfg->perm); umask(mask); /* prepare jittering counter */ cfg->jittercount = 0; /* prepare monitoring time and stat */ if (cfg->monitor >= 1) { if (gettimeofday(&tv, NULL) != -1) cfg->monitortime = tv.tv_sec; else cfg->monitortime = 0; if ( (cfg->fd != -1) && (fstat(cfg->fd, &st) != -1)) { cfg->monitordev = st.st_dev; cfg->monitorino = st.st_ino; } else { cfg->monitordev = 0; cfg->monitorino = 0; } } } /* create channel */ static l2_result_t hook_create(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_file_t *cfg; /* allocate private channel configuration */ if ((cfg = (l2_ch_file_t *)malloc(sizeof(l2_ch_file_t))) == NULL) return L2_ERR_ARG; /* initialize configuration with reasonable defaults */ cfg->fd = -1; cfg->path = NULL; cfg->append = -1; cfg->trunc = -1; cfg->perm = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); cfg->jitter = 0; cfg->jittercount = 0; cfg->monitor = 0; cfg->monitortime = 0; cfg->monitordev = 0; cfg->monitorino = 0; /* 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_file_t *cfg = (l2_ch_file_t *)ctx->vp; l2_param_t pa[7]; l2_result_t rv; l2_env_t *env; /* feed and call generic parameter parsing engine */ L2_PARAM_SET(pa[0], path, STR, &cfg->path); L2_PARAM_SET(pa[1], append, INT, &cfg->append); L2_PARAM_SET(pa[2], trunc, INT, &cfg->trunc); L2_PARAM_SET(pa[3], perm, INT, &cfg->perm); L2_PARAM_SET(pa[4], jitter, INT, &cfg->jitter); L2_PARAM_SET(pa[5], monitor, INT, &cfg->monitor); L2_PARAM_END(pa[6]); l2_channel_env(ch, &env); rv = l2_util_setparams(env, pa, fmt, ap); return rv; } /* open channel */ static l2_result_t hook_open(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_file_t *cfg = (l2_ch_file_t *)ctx->vp; /* "append" backward compatibility; only cfg->trunc is used in the code * make sure append/trunc either both use defaults, both are set different, or only one is set * * truth table for user input, append, trunc => resulting trunc * -----------------+------+------+------------------ * -1 -1 0 (default) * trunc=0 -1 0 0 * trunc=1 -1 1 1 * append=0 0 -1 1 * append=0, trunc=0 0 0 ERROR * append=0, trunc=1 0 1 1 * append=1 1 -1 0 * append=1, trunc=0 1 0 0 * append=1, trunc=1 1 1 ERROR */ if (cfg->append >= 1) cfg->append = 1; /* reduce to -1 (undef), 0 (no), 1 (yes) */ if (cfg->trunc >= 1) cfg->trunc = 1; /* reduce to -1 (undef), 0 (no), 1 (yes) */ if ( cfg->append != -1 && cfg->trunc != -1 && cfg->append == cfg->trunc) /* collision */ return L2_ERR_USE; if ( cfg->trunc == -1) cfg->trunc = (1 - cfg->append) & 1; /* make sure jitter count is positive number */ if (cfg->jitter < 0) return L2_ERR_USE; /* make sure monitor time is positive number */ if (cfg->monitor < 0) return L2_ERR_USE; /* make sure a path was set */ if (cfg->path == NULL) return L2_ERR_USE; /* open channel file */ if (cfg->trunc == 1) openchfile(ctx, ch, O_WRONLY|O_CREAT|O_TRUNC); else openchfile(ctx, ch, O_WRONLY|O_CREAT|O_APPEND); if (cfg->fd == -1) return L2_ERR_SYS; 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_file_t *cfg = (l2_ch_file_t *)ctx->vp; l2_result_t rc = L2_OK; int reopen = 0; struct timeval tv; struct stat st; /* if jittering, count writes and reopen file if jitter threshold is reached or exceeded */ if (cfg->jitter >= 1) { cfg->jittercount++; if (cfg->jittercount >= cfg->jitter) { cfg->jittercount = 0; reopen = 1; } } /* if monitoring, from time to time check for a renamed log and reopen file on detection */ if (cfg->monitor >= 1) { int dostat = 0; if (gettimeofday(&tv, NULL) != -1) { if ((tv.tv_sec - cfg->monitortime) >= cfg->monitor) { cfg->monitortime = tv.tv_sec; dostat = 1; } } else { dostat = 1; } if (dostat == 1) { if (stat(cfg->path, &st) == -1) { reopen = 1; } else { if ( (cfg->monitordev != st.st_dev) || (cfg->monitorino != st.st_ino)) { reopen = 1; } } } } /* close for reopen if required */ if (reopen == 1 && cfg->fd != -1) { close(cfg->fd); cfg->fd = -1; } /* open if required */ if (cfg->fd == -1) { openchfile(ctx, ch, O_WRONLY|O_CREAT|O_APPEND); } if (cfg->fd == -1) return L2_ERR_SYS; /* write message to channel file */ if (write(cfg->fd, buf, buf_size) == -1) rc = L2_ERR_SYS; return rc; } /* close channel */ static l2_result_t hook_close(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_file_t *cfg = (l2_ch_file_t *)ctx->vp; /* close channel file */ close(cfg->fd); cfg->fd = -1; return L2_OK; } /* destroy channel */ static l2_result_t hook_destroy(l2_context_t *ctx, l2_channel_t *ch) { l2_ch_file_t *cfg = (l2_ch_file_t *)ctx->vp; /* destroy channel configuration */ if (cfg->path != NULL) free(cfg->path); free(cfg); return L2_OK; } /* exported channel handler structure */ l2_handler_t l2_handler_file = { "file", L2_CHANNEL_OUTPUT, hook_create, hook_configure, hook_open, hook_write, NULL, hook_close, hook_destroy }; @ 1.33 log @Adjust copyright messages for new year 2005. @ text @d63 8 @ 1.32 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.31 log @add monitor option to file channel @ 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.30 log @remodel jitter from flag to count; move open logic into openchfile() function @ text @d36 3 d49 4 d60 2 d70 17 d106 4 d121 1 a121 1 l2_param_t pa[6]; d131 2 a132 1 L2_PARAM_END(pa[5]); d174 4 d201 2 d210 25 @ 1.29 log @whitespaces @ text @d45 1 d48 15 d73 7 a79 6 cfg->fd = -1; cfg->path = NULL; cfg->append = -1; cfg->trunc = -1; cfg->perm = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); cfg->jitter = 0; d96 5 a100 5 L2_PARAM_SET(pa[0], path, STR, &cfg->path); L2_PARAM_SET(pa[1], append, INT, &cfg->append); L2_PARAM_SET(pa[2], trunc, INT, &cfg->trunc); L2_PARAM_SET(pa[3], perm, INT, &cfg->perm); L2_PARAM_SET(pa[4], jitter, INT, &cfg->jitter); a111 2 int mode; mode_t mask; d139 3 a141 5 /* reduce jitter to 0 (no) or 1 (yes) */ if (cfg->jitter <= 0) cfg->jitter = 0; if (cfg->jitter >= 1) cfg->jitter = 1; a147 1 mode = O_WRONLY|O_CREAT; d149 1 a149 1 mode |= O_TRUNC; d151 2 a152 4 mode |= O_APPEND; mask = umask(0); cfg->fd = open(cfg->path, mode, cfg->perm); umask(mask); a155 6 /* close channel file if jittering, we just wanted to see a successful open and truncate if required */ if (cfg->jitter == 1) { close(cfg->fd); cfg->fd = -1; } d165 10 a174 1 mode_t mask; d176 2 a177 2 /* handle the impossible; close any lingering file if jittering */ if (cfg->fd != -1 && cfg->jitter == 1) { d182 3 a184 5 /* open channel file if jittering */ if (cfg->fd == -1 && cfg->jitter == 1) { mask = umask(0); cfg->fd = open(cfg->path, O_WRONLY|O_CREAT|O_APPEND, cfg->perm); umask(mask); d186 1 a192 6 /* close channel file if jittering */ if (cfg->jitter == 1) { close(cfg->fd); cfg->fd = -1; } @ 1.28 log @add jitter option to file channel @ text @d104 3 a106 3 * trunc=0 -1 0 0 * trunc=1 -1 1 1 * append=0 0 -1 1 d108 3 a110 3 * append=0, trunc=1 0 1 1 * append=1 1 -1 0 * append=1, trunc=0 1 0 0 @ 1.27 log @fix array too small by one element bug @ text @d44 1 d62 1 d74 1 a74 1 l2_param_t pa[5]; d83 2 a84 1 L2_PARAM_END(pa[4]); a87 1 d124 6 d146 6 d160 17 d180 7 a186 1 return L2_ERR_SYS; d188 1 a188 1 return L2_OK; @ 1.26 log @introduce "trunc=" option for file channel; change default to append; keep support for obsolete "append" option @ text @d72 1 a72 1 l2_param_t pa[4]; @ 1.25 log @- remove trailing whitespaces - adjust copyright messages - consistently use "OSSP l2" - consistently talk about "Flexible Logging" - use standard OSSP ASCII-art @ text @d42 1 d58 2 a59 1 cfg->append = TRUE; d79 3 a81 2 L2_PARAM_SET(pa[2], perm, INT, &cfg->perm); L2_PARAM_END(pa[3]); d85 1 d96 26 d128 3 a130 1 if (cfg->append) a131 2 else mode |= O_TRUNC; @ 1.24 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 d55 4 a58 4 cfg->fd = -1; cfg->path = NULL; cfg->append = TRUE; cfg->perm = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); d70 1 a70 1 l2_param_t pa[4]; d116 1 a116 1 @ 1.23 log @allow hexadecimal and octal integer values, too. (especially for file permissions) @ text @d2 1 a2 1 ** L2 - OSSP Logging Library d7 1 a7 1 ** can be found at http://www.ossp.org/pkg/l2/. @ 1.22 log @not append means truncate @ text @d89 1 d101 4 a104 1 if ((cfg->fd = open(cfg->path, mode, cfg->perm)) == -1) @ 1.21 log @bump copyright year @ text @d98 2 @ 1.20 log @Close potential memory leak. @ 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.19 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 @d135 2 @ 1.18 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 @d41 1 a41 1 long perm; d71 1 d74 3 a76 3 L2_PARAM_SET(pa[0], path, CHARPTR, &cfg->path); L2_PARAM_SET(pa[1], append, INT, &cfg->append); L2_PARAM_SET(pa[2], perm, LONG, &cfg->perm); d78 2 a79 1 rv = l2_util_setparams(pa, fmt, ap); @ 1.17 log @Upgraded both stream and channel-level APIs to include new L2_LEVEL parameter design. @ text @d140 1 @ 1.16 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 @d103 2 a104 2 static l2_result_t hook_write(l2_context_t *ctx, l2_channel_t *ch, const char *buf, size_t buf_size) @ 1.15 log @It is fully legal to have some handler operations not implemented in case there is nothing to do for the handler. So remove the No-op hooks. @ text @d68 1 a68 1 l2_ch_file_t *cfg; a71 4 /* parameter checks */ if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) return L2_ERR_ARG; d85 1 a85 1 l2_ch_file_t *cfg; d88 1 a88 3 /* parameter checks */ if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) return L2_ERR_ARG; d106 2 a107 8 l2_ch_file_t *cfg; /* parameter checks */ if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) return L2_ERR_ARG; if (cfg->fd == -1) return L2_ERR_USE; d118 1 a118 7 l2_ch_file_t *cfg; /* parameter checks */ if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) return L2_ERR_ARG; if (cfg->fd == -1) return L2_ERR_USE; d130 1 a130 3 /* parameter checks */ if (ctx->vp == NULL) return L2_ERR_ARG; d133 1 a133 1 free(ctx->vp); @ 1.14 log @Replace generic L2_ERROR with more granular L2_ERR_XXX and make sure that we always check with "!= L2_OK". @ text @a126 8 /* flush channel */ static l2_result_t hook_flush(l2_context_t *ctx, l2_channel_t *ch) { /* NOP for this channel, because Unix I/O files are unbuffered! */ return L2_OK; } d165 1 a165 1 hook_flush, @ 1.13 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 @d51 1 a51 1 return L2_ERROR; d74 1 a74 1 return L2_ERROR; d94 1 a94 1 return L2_ERROR; d96 1 a96 1 return L2_ERROR; d103 1 a103 1 return L2_ERROR; d116 1 a116 1 return L2_ERROR; d118 1 a118 1 return L2_ERROR; d122 1 a122 1 return L2_ERROR; d142 1 a142 1 return L2_ERROR; d144 1 a144 1 return L2_ERROR; d158 1 a158 1 return L2_ERROR; @ 1.12 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.11 log @Whohooo, now we can simplify output channels: because output channels are guarrantied to be not on top of other channels, they do not have any downstream channels. So remove all downstream handling from them. Only filter channels have to be aware of downstream channels. @ text @d46 1 a46 1 static int hook_create(l2_context_t *ctx, l2_channel_t *ch) d67 1 a67 1 static int hook_configure(l2_context_t *ctx, l2_channel_t *ch, const char *fmt, va_list ap) d88 1 a88 1 static int hook_open(l2_context_t *ctx, l2_channel_t *ch) d110 1 a110 1 static int hook_write(l2_context_t *ctx, l2_channel_t *ch, d129 1 a129 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *ch) d137 1 a137 1 static int hook_close(l2_context_t *ctx, l2_channel_t *ch) d155 1 a155 1 static int hook_destroy(l2_context_t *ctx, l2_channel_t *ch) @ 1.10 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 @a90 1 l2_channel_t *downstream; a105 5 /* optionally open downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_open(downstream) == L2_ERROR) return L2_ERROR; a113 1 l2_channel_t *downstream; a124 5 /* optionally write to downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_write(downstream, buf, buf_size) == L2_ERROR) return L2_ERROR; a130 2 l2_channel_t *downstream; a132 5 /* optionally flush downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_flush(downstream) == L2_ERROR) return L2_ERROR; a139 6 l2_channel_t *downstream; /* optionally close downstream channel, too */ if ((downstream = l2_channel_downstream(ch)) != NULL) if (l2_channel_close(downstream) == L2_ERROR) return L2_ERROR; @ 1.9 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 @d46 1 a46 1 static int hook_create(l2_context_t *ctx) d67 1 a67 1 static int hook_configure(l2_context_t *ctx, const char *fmt, va_list ap) d88 1 a88 1 static int hook_open(l2_context_t *ctx, l2_channel_t *downstream) d91 1 d108 1 a108 1 if (downstream != NULL) d116 1 a116 1 static int hook_write(l2_context_t *ctx, l2_channel_t *downstream, d120 1 d133 1 a133 1 if (downstream != NULL) d141 1 a141 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *downstream) d143 2 d148 1 a148 1 if (downstream != NULL) d156 1 a156 1 static int hook_close(l2_context_t *ctx, l2_channel_t *downstream) d159 1 d162 1 a162 1 if (downstream != NULL) d180 1 a180 1 static int hook_destroy(l2_context_t *ctx) d194 1 @ 1.8 log @fix configuration bug in file channel @ text @d82 1 a82 1 rv = l2_channel_setparams(pa, fmt, ap); @ 1.7 log @Fix more ossp.com references by replacing with the correct domain name ossp.org. @ text @d70 1 a70 1 l2_param_t pa[3]; d80 2 a81 2 L2_PARAM_SET(pa[1], perm, LONG, &cfg->perm); L2_PARAM_END(pa[2]); @ 1.6 log @o rename l2_error_t to l2_result_t o introduce internal channel state for API robustness @ text @d7 1 a7 1 ** can be found at http://www.ossp.com/pkg/l2/. @ 1.5 log @Simplify things by merging the parameter stuff into l2_channel.c and the l2_stream_t related things into l2_stream.c @ text @d71 1 a71 1 l2_error_t rv; @ 1.4 log @Simplify the file handler, because a NULL ctx cannot happen at all. @ text @d82 1 a82 1 rv = l2_param_parse(pa, fmt, ap); @ 1.3 log @Give us a clue how the handler functions actually should look now that we have l2_param_parse() and friends available. So to help Peti in approaching milestone 2 for Monday, I felt free to implement l2_handler_file for us, based on raw Unix I/O. @ text @a73 2 if (ctx == NULL) return L2_ERROR; a93 2 if (ctx == NULL) return L2_ERROR; a120 2 if (ctx == NULL) return L2_ERROR; a161 2 if (ctx == NULL) return L2_ERROR; a177 2 if (ctx == NULL) return L2_ERROR; @ 1.2 log @Fill in channel handler template code. @ text @d33 13 d48 15 d66 1 d69 18 a86 1 return L2_OK; d89 2 a90 1 static int hook_open(l2_context_t *ctx, l2_channel_t *below) d92 23 d118 2 a119 1 static int hook_write(l2_context_t *ctx, l2_channel_t *below, d122 19 d144 2 a145 1 static int hook_flush(l2_context_t *ctx, l2_channel_t *below) d147 7 d157 2 a158 1 static int hook_close(l2_context_t *ctx, l2_channel_t *below) d160 19 d182 1 d185 9 d197 1 @ 1.1 log @Initial revision @ text @d1 28 d33 25 a57 1 #if 0 d59 1 a59 1 int l2_file_create(l2_channel_t *ch) d61 1 a61 1 return; d64 13 a76 8 l2_handler_t l2_handler_file { l2_file_create, l2_file_configure, l2_file_open, l2_file_write, l2_file_flush, l2_file_close, l2_file_destroy a77 2 #endif @ 1.1.1.1 log @L2 initial source tree @ text @@