Index: ossp-pkg/l2/l2_ch_file.c RCS File: /v/ossp/cvs/ossp-pkg/l2/l2_ch_file.c,v rcsdiff -q -kk '-r1.2' '-r1.3' -u '/v/ossp/cvs/ossp-pkg/l2/l2_ch_file.c,v' 2>/dev/null --- l2_ch_file.c 2001/05/11 17:07:52 1.2 +++ l2_ch_file.c 2001/05/19 20:14:15 1.3 @@ -30,42 +30,171 @@ #include "l2.h" #include "l2_p.h" +#include +#include +#include + +/* declare private channel configuration */ +typedef struct { + int fd; + char *path; + int append; + long perm; +} l2_ch_file_t; + +/* create channel */ static int hook_create(l2_context_t *ctx) { + l2_ch_file_t *cfg; + + /* allocate private channel configuration */ + if ((cfg = (l2_ch_file_t *)malloc(sizeof(l2_ch_file_t))) == NULL) + return L2_ERROR; + + /* initialize configuration with reasonable defaults */ + cfg->fd = -1; + cfg->path = NULL; + cfg->append = TRUE; + cfg->perm = (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + + /* link private channel configuration into channel context */ + ctx->vp = cfg; + return L2_OK; } +/* configure channel */ static int hook_configure(l2_context_t *ctx, const char *fmt, va_list ap) { - return L2_OK; + l2_ch_file_t *cfg; + l2_param_t pa[3]; + l2_error_t rv; + + /* parameter checks */ + if (ctx == NULL) + return L2_ERROR; + if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) + return L2_ERROR; + + /* feed and call generic parameter parsing engine */ + L2_PARAM_SET(pa[0], path, CHARPTR, &cfg->path); + L2_PARAM_SET(pa[1], append, INT, &cfg->append); + L2_PARAM_SET(pa[1], perm, LONG, &cfg->perm); + L2_PARAM_END(pa[2]); + rv = l2_param_parse(pa, fmt, ap); + + return rv; } -static int hook_open(l2_context_t *ctx, l2_channel_t *below) +/* open channel */ +static int hook_open(l2_context_t *ctx, l2_channel_t *downstream) { + l2_ch_file_t *cfg; + int mode; + + /* parameter checks */ + if (ctx == NULL) + return L2_ERROR; + if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) + return L2_ERROR; + if (cfg->path == NULL) + return L2_ERROR; + + /* open channel file */ + mode = O_WRONLY|O_CREAT; + if (cfg->append) + mode |= O_APPEND; + if ((cfg->fd = open(cfg->path, mode, cfg->perm)) == -1) + return L2_ERROR; + + /* optionally open downstream channel, too */ + if (downstream != NULL) + if (l2_channel_open(downstream) == L2_ERROR) + return L2_ERROR; + return L2_OK; } -static int hook_write(l2_context_t *ctx, l2_channel_t *below, +/* write to channel */ +static int hook_write(l2_context_t *ctx, l2_channel_t *downstream, const char *buf, size_t buf_size) { + l2_ch_file_t *cfg; + + /* parameter checks */ + if (ctx == NULL) + return L2_ERROR; + if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) + return L2_ERROR; + if (cfg->fd == -1) + return L2_ERROR; + + /* write message to channel file */ + if (write(cfg->fd, buf, buf_size) == -1) + return L2_ERROR; + + /* optionally write to downstream channel, too */ + if (downstream != NULL) + if (l2_channel_write(downstream, buf, buf_size) == L2_ERROR) + return L2_ERROR; + return L2_OK; } -static int hook_flush(l2_context_t *ctx, l2_channel_t *below) +/* flush channel */ +static int hook_flush(l2_context_t *ctx, l2_channel_t *downstream) { + /* NOP for this channel, because Unix I/O files are unbuffered! */ + + /* optionally flush downstream channel, too */ + if (downstream != NULL) + if (l2_channel_flush(downstream) == L2_ERROR) + return L2_ERROR; + return L2_OK; } -static int hook_close(l2_context_t *ctx, l2_channel_t *below) +/* close channel */ +static int hook_close(l2_context_t *ctx, l2_channel_t *downstream) { + l2_ch_file_t *cfg; + + /* optionally close downstream channel, too */ + if (downstream != NULL) + if (l2_channel_close(downstream) == L2_ERROR) + return L2_ERROR; + + /* parameter checks */ + if (ctx == NULL) + return L2_ERROR; + if ((cfg = (l2_ch_file_t *)ctx->vp) == NULL) + return L2_ERROR; + if (cfg->fd == -1) + return L2_ERROR; + + /* close channel file */ + close(cfg->fd); + cfg->fd = -1; + return L2_OK; } +/* destroy channel */ static int hook_destroy(l2_context_t *ctx) { + /* parameter checks */ + if (ctx == NULL) + return L2_ERROR; + if (ctx->vp == NULL) + return L2_ERROR; + + /* destroy channel configuration */ + free(ctx->vp); + return L2_OK; } +/* exported channel handler structure */ l2_handler_t l2_handler_file = { hook_create, hook_configure,