Index: ossp-pkg/sio/sio.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/sio.c,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio.c' 2>/dev/null --- ossp-pkg/sio/sio.c +++ - 2024-05-22 04:48:44.705845219 +0200 @@ -0,0 +1,409 @@ +/* +** OSSP sio -- stream I/O +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 Michael van Elst +** +** This file is part of OSSP sio, a library implementing layered I/O +** +** 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. +** +** sio.c: stream I/O library implementation +*/ + +#include +#include + +#include "al.h" +#include "sio.h" +#include "sio_module.h" +#include "list.h" + +/****************************************************************************/ + +/* unique library identifier */ +const char sio_id[] = "OSSP sio"; + +/* support for OSSP ex based exception throwing */ +#ifdef WITH_EX +#include "ex.h" +#define SIO_RC(rv) \ + ( (rv) != SIO_OK && (ex_catching && !ex_shielding) \ + ? (ex_throw(sio_id, NULL, (rv)), (rv)) : (rv) ) +#else +#define SIO_RC(rv) (rv) +#endif /* WITH_EX */ + + +struct sio_halfduplex_st; +typedef struct sio_halfduplex_st sio_halfduplex_t; +struct sio_halfduplex_st { + NODE(sio_halfduplex_t) hd; + sio_stage_t *stage; + sio_rc_t (*func)(sio_t *, al_t *, void *); +}; + +struct sio_st { + struct { + LIST(sio_halfduplex_t) hd; + al_t *al; + } readers; + struct { + LIST(sio_halfduplex_t) hd; + al_t *al; + } writers; +}; + +struct sio_stage_st { + sio_halfduplex_t reader; + sio_halfduplex_t writer; + void *userdata; + sio_module_t *module; + sio_mode_t rw; +}; + +/****************************************************************************/ + +static +sio_rc_t sio_strategy(sio_t *sio, sio_halfduplex_t *chain, al_t *al) +{ + sio_rc_t rc; + sio_halfduplex_t *h; + + h = chain; + while (h != NULL) { + rc = h->func(sio, al, h->stage->userdata); + if (rc == SIO_UPSTREAM) + h = NEXT(h,hd); + else if (rc == SIO_DOWNSTREAM) + h = NEXT(h,hd); + else + break; + } + + return SIO_OK; +} + +/**************************************************************************/ + +sio_rc_t sio_create(sio_t **siop) +{ + sio_t *sio; + + /* argument sanity check(s) */ + if (siop == NULL) + return SIO_RC(SIO_ERR_ARG); + + sio = (sio_t *)malloc(sizeof(sio_t)); + if (sio == NULL) + return SIO_RC(SIO_ERR_MEM); + + LISTINIT(&sio->readers,hd); + LISTINIT(&sio->writers,hd); + + *siop = sio; + + return SIO_OK; +} + +sio_rc_t sio_destroy(sio_t *sio) +{ + /* argument sanity check(s) */ + if (sio == NULL) + return SIO_RC(SIO_ERR_ARG); + + free(sio); + + return SIO_OK; +} + +sio_rc_t sio_create_stage(sio_t *sio, sio_module_t *siom, sio_stage_t **siosp) +{ + sio_rc_t rc; + sio_stage_t *sios; + void *u; + + /* argument sanity check(s) */ + if (sio == NULL || siom == NULL || siosp == NULL) + return SIO_RC(SIO_ERR_ARG); + + sios = (sio_stage_t *)malloc(sizeof(sio_stage_t)); + if (sios == NULL) + return SIO_RC(SIO_ERR_MEM); + + NODEINIT(&sios->reader,hd); + NODEINIT(&sios->writer,hd); + sios->module = siom; + sios->userdata = u; + sios->rw = SIO_MODE_INVALID; + sios->reader.func = siom->input; + sios->reader.stage = sios; + sios->writer.func = siom->output; + sios->writer.stage = sios; + + rc = sios->module->init(sio, sios->userdata); + + return SIO_RC(rc); +} + +sio_rc_t sio_cofigure_stage(sio_t *sio, sio_stage_t *sios, void *obj, void *value) +{ + sio_rc_t rc; + + /* argument sanity check(s) */ + if (sio == NULL || sios == NULL) + return SIO_RC(SIO_ERR_ARG); + + rc = sios->module->configure(sio, sios->userdata, obj, value); + + return SIO_RC(rc); +} + +sio_rc_t sio_destroy_stage(sio_t *sio, sio_stage_t *sios) +{ + sio_rc_t rc; + + /* argument sanity check(s) */ + if (sio == NULL || sios == NULL) + return SIO_RC(SIO_ERR_ARG); + + rc = sios->module->cleanup(sio, sios->userdata); + free(sios); + + return SIO_OK; +} + +sio_rc_t sio_attach(sio_t *sio, sio_stage_t *sios, sio_mode_t rw) +{ + sio_rc_t rc; + + /* argument sanity check(s) */ + if (sio == NULL || sios == NULL) + return SIO_RC(SIO_ERR_ARG); + + /* is module already attached ? */ + if (sios->rw != SIO_MODE_INVALID) + return SIO_RC(SIO_ERR_ARG); + + /* prepare module for being attached */ + rc = sios->module->open(sio, sios->userdata); + if (rc != SIO_OK) return SIO_RC(rc); + + switch (rw) { + case SIO_MODE_READ: + ADDTAIL(&sio->readers,hd,&sios->reader); + break; + case SIO_MODE_WRITE: + ADDTAIL(&sio->writers,hd,&sios->writer); + break; + case SIO_MODE_READWRITE: + ADDTAIL(&sio->readers,hd,&sios->reader); + ADDTAIL(&sio->writers,hd,&sios->writer); + break; + default: + return SIO_RC(SIO_ERR_ARG); + } + + /* Remember the lists that sios has been attached to */ + sios->rw = rw; + + return SIO_OK; +} + +sio_rc_t sio_detach(sio_t *sio, sio_stage_t *sios) +{ + sio_rc_t rc; + + /* argument sanity check(s) */ + if (sio == NULL || sios == NULL) + return SIO_RC(SIO_ERR_ARG); + + switch (sios->rw) { + case SIO_MODE_READ: + REMOVE(&sio->readers,hd,&sios->reader); + break; + case SIO_MODE_WRITE: + REMOVE(&sio->writers,hd,&sios->writer); + break; + case SIO_MODE_READWRITE: + REMOVE(&sio->readers,hd,&sios->reader); + REMOVE(&sio->writers,hd,&sios->writer); + break; + default: + return SIO_RC(SIO_ERR_ARG); + break; + } + + rc = sios->module->close(sio, sios->userdata); + + return SIO_RC(rc); +} + +sio_rc_t sio_input(sio_t *sio, al_t *al, size_t limit) +{ + sio_rc_t rc; + al_t *src = sio->readers.al; + size_t n; + + /* argument sanity check(s) */ + if (sio == NULL || al == NULL) + return SIO_RC(SIO_ERR_ARG); + + n = al_bytes(src); + if (n == 0) { + + rc = sio_strategy(sio, HEAD(&sio->readers,hd), src); + if (rc != SIO_OK) return SIO_RC(rc); + + n = al_bytes(src); + if (n == 0) + return SIO_RC(SIO_ERR_EOF); + + } + + if (n > limit) + n = limit; + + (void) al_splice(src, 0, n, NULL, al); /* XXX - error handling ? */ + + return SIO_OK; +} + +sio_rc_t sio_discard(sio_t *sio) +{ + sio_rc_t rc; + al_t *src = sio->readers.al; + size_t n; + + /* argument sanity check(s) */ + if (sio == NULL) + return SIO_RC(SIO_ERR_ARG); + + while ((n = al_bytes(src)) > 0) { + rc = sio_strategy(sio, HEAD(&sio->readers,hd), src); + if (rc != SIO_OK) + break; + } + + if (rc == SIO_ERR_EOF) + return SIO_OK; + + return SIO_RC(rc); +} + +sio_rc_t sio_output(sio_t *sio, al_t *al) +{ + sio_rc_t rc; + al_t *dst = sio->writers.al; + size_t n; + + /* argument sanity check(s) */ + if (sio == NULL || al == NULL) + return SIO_RC(SIO_ERR_ARG); + + n = al_bytes(dst); + al_splice(dst, n, 0, al, NULL); + + rc = sio_strategy(sio, HEAD(&sio->writers,hd), dst); + + return SIO_RC(rc); +} + +sio_rc_t sio_flush(sio_t *sio) +{ + sio_rc_t rc; + al_t *dst = sio->writers.al; + size_t n; + + /* argument sanity check(s) */ + if (sio == NULL) + return SIO_RC(SIO_ERR_ARG); + + while ((n = al_bytes(dst)) > 0) { + rc = sio_strategy(sio, HEAD(&sio->writers,hd), sio->writers.al); + if (rc != SIO_OK) + break; + } + + return SIO_RC(rc); +} + +sio_rc_t sio_read(sio_t *sio, char *dst, size_t n, size_t *actualp) +{ + al_rc_t arc; + sio_rc_t rc; + al_t *al; + + arc = al_create(&al); + if (arc != AL_OK) return SIO_RC(SIO_ERR_INT); + + rc = sio_input(sio, al, n); + if (rc == AL_OK) { + arc = al_flatten(al, 0, n, dst, actualp); + if (arc != AL_OK) + rc = SIO_ERR_INT; + } + + arc = al_destroy(al); + if (arc != AL_OK) return SIO_RC(SIO_ERR_INT); + + return SIO_RC(rc); +} + +sio_rc_t sio_write(sio_t *sio, char *src, size_t n, size_t *actualp) +{ + al_rc_t arc; + sio_rc_t rc; + al_t *al; + + arc = al_create(&al); + if (arc != AL_OK) return SIO_RC(SIO_ERR_INT); + + arc = al_append_bytes(al, src, n); + if (arc != AL_OK) + rc = SIO_ERR_INT; + else + rc = sio_output(sio, al); + + arc = al_destroy(al); + if (arc != AL_OK) return SIO_RC(SIO_ERR_INT); + + return SIO_RC(rc); +} + +const char *sio_error(sio_rc_t rc) +{ + const char *mess; + + switch (rc) { + case SIO_OK: mess = "Everything Ok"; break; + case SIO_ERR_ARG: mess = "Invalid Argument"; break; + case SIO_ERR_MEM: mess = "Not Enough Memory"; break; + case SIO_ERR_EOF: mess = "End Of Data"; break; + case SIO_ERR_SYS: mess = "Operating System Error"; break; + case SIO_ERR_INT: mess = "Internal Error"; break; + case SIO_UPSTREAM: mess = "Invoke Upstream Stage"; break; + case SIO_DOWNSTREAM: mess = "Invoke Downstream Stage"; break; + default: mess = "Invalid Result Code"; break; + } + + return mess; +} + Index: ossp-pkg/sio/sio.h RCS File: /v/ossp/cvs/ossp-pkg/sio/sio.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/sio.h,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio.h' 2>/dev/null --- ossp-pkg/sio/sio.h +++ - 2024-05-22 04:48:44.708859294 +0200 @@ -0,0 +1,74 @@ +/* +** OSSP sio -- Stream I/O +** Copyright (c) 2002 The OSSP Project +** Copyright (c) 2002 Cable & Wireless Deutschland +** Copyright (c) 2002 Ralf S. Engelschall +** Copyright (c) 2002 Michael van Elst +** +** This file is part of OSSP sio, a library implementing layered I/O +** +** 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. +** +** sio.h: stream I/O public API definition +*/ + +typedef enum { + SIO_OK, + SIO_ERR_ARG, + SIO_ERR_MEM, + SIO_ERR_EOF, + SIO_ERR_SYS, + SIO_ERR_INT, + SIO_UPSTREAM, + SIO_DOWNSTREAM +} sio_rc_t; + +typedef enum { + SIO_MODE_INVALID, + SIO_MODE_READ, + SIO_MODE_WRITE, + SIO_MODE_READWRITE +} sio_mode_t; + +struct sio_st; +typedef struct sio_st sio_t; + +struct sio_stage_st; +typedef struct sio_stage_st sio_stage_t; + +struct sio_module_st; +typedef struct sio_module_st sio_module_t; + +sio_rc_t sio_create(sio_t **siop); +sio_rc_t sio_destroy(sio_t *sio); + +sio_rc_t sio_create_stage(sio_t *sio, sio_module_t *sioh, sio_stage_t **siosp); +sio_rc_t sio_destroy_stage(sio_t *sio, sio_stage_t *sios); +sio_rc_t sio_configure_stage(sio_t *sio, sio_stage_t *sios, void *o, void *v); + +sio_rc_t sio_attach(sio_t *sio, sio_stage_t *sios, sio_mode_t rw); +sio_rc_t sio_detach(sio_t *sio, sio_stage_t *sios); + +sio_rc_t sio_input(sio_t *sio, al_t *al, size_t limit); +sio_rc_t sio_output(sio_t *sio, al_t *al); + +sio_rc_t sio_read(sio_t *sio, char *dst, size_t n, size_t *actualp); +sio_rc_t sio_write(sio_t *sio, char *src, size_t n, size_t *actualp); + +const char *sio_error(sio_rc_t rc); Index: ossp-pkg/sio/sio_fd.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_fd.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/sio_fd.c,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio_fd.c' 2>/dev/null --- ossp-pkg/sio/sio_fd.c +++ - 2024-05-22 04:48:44.711536731 +0200 @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include + +#include "al.h" +#include "sio.h" +#include "sio_module.h" + +typedef struct { + int fd; + size_t buflen; + char *buf; + size_t actual; +} private_t; + +/* + * create stage + * + * allocate private instance data + */ +static +sio_rc_t fd_init(sio_t *sio, void **u) +{ + private_t *mydata; + + mydata = (private_t *)malloc(sizeof(private_t)); + if (mydata == NULL) + return SIO_ERR_MEM; + + mydata->fd = -1; + mydata->buflen = 0; + mydata->buf = NULL; + + *u = mydata; + + return SIO_OK; +} + +/* + * configure stage + * + */ +static +sio_rc_t fd_configure(sio_t *sio, void *u, void *obj, void *value) +{ + private_t *mydata = (private_t *)u; + const char *name = (const char *)obj; + char *newbuf; + + if (!strcmp(name, "fd")) { + mydata->fd = *(int *)value; + } else if (!strcmp(name, "buflen")) { + mydata->buflen = *(int *)value; + newbuf = realloc(mydata->buf, mydata->buflen); + if (newbuf == NULL) + return SIO_ERR_MEM; + mydata->buf = newbuf; + } else { + return SIO_ERR_ARG; + } + + return SIO_OK; +} + +/* + * destroy stage + */ +static +sio_rc_t fd_cleanup(sio_t *sio, void *u) +{ + private_t *mydata = (private_t *)u; + + if (mydata->buf) free(mydata->buf); + free(mydata); + + return SIO_OK; +} + +static +sio_rc_t fd_open(sio_t *sio, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t fd_close(sio_t *sio, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t fd_input(sio_t *sio, al_t *al, void *u) +{ + private_t *mydata = (private_t *)u; + size_t actual; + + if (mydata->buf == NULL) + return SIO_ERR_ARG; + + actual = read(mydata->fd, mydata->buf, mydata->buflen); + if (actual < 0) + return SIO_ERR_SYS; + + al_append_bytes(al, mydata->buf, actual); + + return SIO_OK; +} + +static +al_rc_t fd_output_chunk(al_chunk_t *alc, void *u) +{ + private_t *mydata = (private_t *)u; + char *p; + size_t n, actual; + + p = al_chunk_ptr(alc, 0); + n = al_chunk_len(alc); + + actual = write(mydata->fd, p, n); + if (actual < 0) + return AL_ERR_EOF; + + mydata->actual += actual; + + return AL_OK; +} + +static +sio_rc_t fd_output(sio_t *sio, al_t *al, void *u) +{ + private_t *mydata = (private_t *)u; + al_rc_t arc; + size_t n = al_bytes(al); + + mydata->actual = 0; + + arc = al_traverse_cb(al, 0, n, AL_FORWARD, fd_output_chunk, u); + if (arc != AL_OK) return SIO_ERR_INT; + + arc = al_splice(al, 0, mydata->actual, NULL, NULL); + if (arc != AL_OK) return SIO_ERR_INT; + + return SIO_OK; +} + +sio_module_t sio_fd_module = { + "fd", + fd_init, + fd_configure, + fd_cleanup, + fd_open, + fd_close, + fd_input, + fd_output +}; + + Index: ossp-pkg/sio/sio_module.h RCS File: /v/ossp/cvs/ossp-pkg/sio/Attic/sio_module.h,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/Attic/sio_module.h,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio_module.h' 2>/dev/null --- ossp-pkg/sio/sio_module.h +++ - 2024-05-22 04:48:44.714232122 +0200 @@ -0,0 +1,11 @@ +struct sio_module_st { + const char *name; + sio_rc_t (*init) (sio_t *, void **); + sio_rc_t (*configure) (sio_t *, void *, void *, void *); + sio_rc_t (*cleanup) (sio_t *, void *); + sio_rc_t (*open) (sio_t *, void *); + sio_rc_t (*close) (sio_t *, void *); + sio_rc_t (*input) (sio_t *, al_t *, void *); + sio_rc_t (*output) (sio_t *, al_t *, void *); +}; + Index: ossp-pkg/sio/sio_null.c RCS File: /v/ossp/cvs/ossp-pkg/sio/sio_null.c,v co -q -kk -p'1.1' '/v/ossp/cvs/ossp-pkg/sio/sio_null.c,v' | diff -u /dev/null - -L'ossp-pkg/sio/sio_null.c' 2>/dev/null --- ossp-pkg/sio/sio_null.c +++ - 2024-05-22 04:48:44.716792316 +0200 @@ -0,0 +1,99 @@ +#include +#include + +#include "al.h" +#include "sio.h" +#include "sio_module.h" + +typedef struct { + int a; + float b; + char *c; +} private_t; + +/* + * create stage + * + * allocate private instance data + */ +static +sio_rc_t null_init(sio_t *sio, void **u) +{ + private_t *mydata; + + mydata = (private_t *)malloc(sizeof(private_t)); + if (mydata == NULL) + return SIO_ERR_MEM; + + mydata->a = 42; + mydata->b = 42.0; + mydata->c = "42"; + + *u = mydata; + + return SIO_OK; +} + +/* + * configure stage + * + * pass two void pointers + */ +static +sio_rc_t null_configure(sio_t *sio, void *u, void *obj, void *val) +{ + private_t *mydata = (private_t *)u; + + mydata->a = *(int *)val; + + return SIO_OK; +} + +/* + * destroy stage + */ +static +sio_rc_t null_cleanup(sio_t *sio, void *u) +{ + private_t *mydata = (private_t *)u; + + free(mydata); + + return SIO_OK; +} + +static +sio_rc_t null_open(sio_t *sio, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t null_close(sio_t *sio, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t null_input(sio_t *sio, al_t *al, void *u) +{ + return SIO_OK; +} + +static +sio_rc_t null_output(sio_t *sio, al_t *al, void *u) +{ + return SIO_OK; +} + +sio_module_t sio_null_module = { + "null", + null_init, + null_configure, + null_cleanup, + null_open, + null_close, + null_input, + null_output +}; +