implemented a primitive wrapper device for a system handle

This commit is contained in:
hyung-hwan 2022-02-15 11:14:10 +00:00
parent 5cfc34daaa
commit 10123109b0
8 changed files with 522 additions and 42 deletions

View File

@ -52,6 +52,7 @@ include_HEADERS = \
hio-pty.h \
hio-rad.h \
hio-sck.h \
hio-shw.h \
hio-skad.h \
hio-thr.h \
hio-upac.h \
@ -92,6 +93,7 @@ libhio_la_SOURCES = \
pty.c \
rad-msg.c \
sck.c \
shw.c \
skad.c \
sys.c \
sys-ass.c \

View File

@ -151,7 +151,7 @@ am__libhio_la_SOURCES_DIST = chr.c dhcp-svr.c dns.c dns-cli.c ecs.c \
ecs-imp.h err.c fmt.c fmt-imp.h htb.c htrd.c htre.c http.c \
http-cgi.c http-fil.c http-prv.h http-svr.c http-thr.c \
http-txt.c json.c hio-prv.h hio.c md5.c nwif.c opt.c opt-imp.h \
path.c pipe.c pro.c pty.c rad-msg.c sck.c skad.c sys.c \
path.c pipe.c pro.c pty.c rad-msg.c sck.c shw.c skad.c sys.c \
sys-ass.c sys-err.c sys-log.c sys-mux.c sys-prv.h sys-tim.c \
thr.c uch-case.h uch-prop.h tmr.c utf8.c utl.c utl-siph.c \
utl-str.c mar.c mar-cli.c
@ -167,11 +167,11 @@ am_libhio_la_OBJECTS = libhio_la-chr.lo libhio_la-dhcp-svr.lo \
libhio_la-md5.lo libhio_la-nwif.lo libhio_la-opt.lo \
libhio_la-path.lo libhio_la-pipe.lo libhio_la-pro.lo \
libhio_la-pty.lo libhio_la-rad-msg.lo libhio_la-sck.lo \
libhio_la-skad.lo libhio_la-sys.lo libhio_la-sys-ass.lo \
libhio_la-sys-err.lo libhio_la-sys-log.lo libhio_la-sys-mux.lo \
libhio_la-sys-tim.lo libhio_la-thr.lo libhio_la-tmr.lo \
libhio_la-utf8.lo libhio_la-utl.lo libhio_la-utl-siph.lo \
libhio_la-utl-str.lo $(am__objects_1)
libhio_la-shw.lo libhio_la-skad.lo libhio_la-sys.lo \
libhio_la-sys-ass.lo libhio_la-sys-err.lo libhio_la-sys-log.lo \
libhio_la-sys-mux.lo libhio_la-sys-tim.lo libhio_la-thr.lo \
libhio_la-tmr.lo libhio_la-utf8.lo libhio_la-utl.lo \
libhio_la-utl-siph.lo libhio_la-utl-str.lo $(am__objects_1)
libhio_la_OBJECTS = $(am_libhio_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -214,7 +214,8 @@ am__depfiles_remade = ./$(DEPDIR)/libhio_la-chr.Plo \
./$(DEPDIR)/libhio_la-path.Plo ./$(DEPDIR)/libhio_la-pipe.Plo \
./$(DEPDIR)/libhio_la-pro.Plo ./$(DEPDIR)/libhio_la-pty.Plo \
./$(DEPDIR)/libhio_la-rad-msg.Plo \
./$(DEPDIR)/libhio_la-sck.Plo ./$(DEPDIR)/libhio_la-skad.Plo \
./$(DEPDIR)/libhio_la-sck.Plo ./$(DEPDIR)/libhio_la-shw.Plo \
./$(DEPDIR)/libhio_la-skad.Plo \
./$(DEPDIR)/libhio_la-sys-ass.Plo \
./$(DEPDIR)/libhio_la-sys-err.Plo \
./$(DEPDIR)/libhio_la-sys-log.Plo \
@ -255,7 +256,8 @@ am__include_HEADERS_DIST = hio-chr.h hio-cmn.h hio-dhcp.h hio-dns.h \
hio-ecs.h hio-fmt.h hio-htb.h hio-htrd.h hio-htre.h hio-http.h \
hio-json.h hio-md5.h hio-nwif.h hio-opt.h hio-pac1.h \
hio-path.h hio-pipe.h hio-pro.h hio-pty.h hio-rad.h hio-sck.h \
hio-skad.h hio-thr.h hio-upac.h hio-utl.h hio.h hio-mar.h
hio-shw.h hio-skad.h hio-thr.h hio-upac.h hio-utl.h hio.h \
hio-mar.h
HEADERS = $(include_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
hio-cfg.h.in
@ -453,16 +455,16 @@ include_HEADERS = hio-chr.h hio-cmn.h hio-dhcp.h hio-dns.h hio-ecs.h \
hio-fmt.h hio-htb.h hio-htrd.h hio-htre.h hio-http.h \
hio-json.h hio-md5.h hio-nwif.h hio-opt.h hio-pac1.h \
hio-path.h hio-pipe.h hio-pro.h hio-pty.h hio-rad.h hio-sck.h \
hio-skad.h hio-thr.h hio-upac.h hio-utl.h hio.h \
hio-shw.h hio-skad.h hio-thr.h hio-upac.h hio-utl.h hio.h \
$(am__append_1)
lib_LTLIBRARIES = libhio.la
libhio_la_SOURCES = chr.c dhcp-svr.c dns.c dns-cli.c ecs.c ecs-imp.h \
err.c fmt.c fmt-imp.h htb.c htrd.c htre.c http.c http-cgi.c \
http-fil.c http-prv.h http-svr.c http-thr.c http-txt.c json.c \
hio-prv.h hio.c md5.c nwif.c opt.c opt-imp.h path.c pipe.c \
pro.c pty.c rad-msg.c sck.c skad.c sys.c sys-ass.c sys-err.c \
sys-log.c sys-mux.c sys-prv.h sys-tim.c thr.c uch-case.h \
uch-prop.h tmr.c utf8.c utl.c utl-siph.c utl-str.c \
pro.c pty.c rad-msg.c sck.c shw.c skad.c sys.c sys-ass.c \
sys-err.c sys-log.c sys-mux.c sys-prv.h sys-tim.c thr.c \
uch-case.h uch-prop.h tmr.c utf8.c utl.c utl-siph.c utl-str.c \
$(am__append_2)
libhio_la_CPPFLAGS = $(CPPFLAGS_LIB_COMMON)
libhio_la_CFLAGS = $(CFLAGS_LIB_COMMON) $(am__append_3)
@ -592,6 +594,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-pty.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-rad-msg.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-sck.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-shw.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-skad.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-sys-ass.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libhio_la-sys-err.Plo@am__quote@ # am--include-marker
@ -825,6 +828,13 @@ libhio_la-sck.lo: sck.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhio_la_CPPFLAGS) $(CPPFLAGS) $(libhio_la_CFLAGS) $(CFLAGS) -c -o libhio_la-sck.lo `test -f 'sck.c' || echo '$(srcdir)/'`sck.c
libhio_la-shw.lo: shw.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhio_la_CPPFLAGS) $(CPPFLAGS) $(libhio_la_CFLAGS) $(CFLAGS) -MT libhio_la-shw.lo -MD -MP -MF $(DEPDIR)/libhio_la-shw.Tpo -c -o libhio_la-shw.lo `test -f 'shw.c' || echo '$(srcdir)/'`shw.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhio_la-shw.Tpo $(DEPDIR)/libhio_la-shw.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='shw.c' object='libhio_la-shw.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhio_la_CPPFLAGS) $(CPPFLAGS) $(libhio_la_CFLAGS) $(CFLAGS) -c -o libhio_la-shw.lo `test -f 'shw.c' || echo '$(srcdir)/'`shw.c
libhio_la-skad.lo: skad.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libhio_la_CPPFLAGS) $(CPPFLAGS) $(libhio_la_CFLAGS) $(CFLAGS) -MT libhio_la-skad.lo -MD -MP -MF $(DEPDIR)/libhio_la-skad.Tpo -c -o libhio_la-skad.lo `test -f 'skad.c' || echo '$(srcdir)/'`skad.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libhio_la-skad.Tpo $(DEPDIR)/libhio_la-skad.Plo
@ -1114,6 +1124,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/libhio_la-pty.Plo
-rm -f ./$(DEPDIR)/libhio_la-rad-msg.Plo
-rm -f ./$(DEPDIR)/libhio_la-sck.Plo
-rm -f ./$(DEPDIR)/libhio_la-shw.Plo
-rm -f ./$(DEPDIR)/libhio_la-skad.Plo
-rm -f ./$(DEPDIR)/libhio_la-sys-ass.Plo
-rm -f ./$(DEPDIR)/libhio_la-sys-err.Plo
@ -1202,6 +1213,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/libhio_la-pty.Plo
-rm -f ./$(DEPDIR)/libhio_la-rad-msg.Plo
-rm -f ./$(DEPDIR)/libhio_la-sck.Plo
-rm -f ./$(DEPDIR)/libhio_la-shw.Plo
-rm -f ./$(DEPDIR)/libhio_la-skad.Plo
-rm -f ./$(DEPDIR)/libhio_la-sys-ass.Plo
-rm -f ./$(DEPDIR)/libhio_la-sys-err.Plo

View File

@ -103,6 +103,7 @@ enum hio_dev_pro_make_flag_t
HIO_DEV_PRO_DROPOUT = (1 << 9),
HIO_DEV_PRO_DROPERR = (1 << 10),
HIO_DEV_PRO_UCMD = (1 << 12), /* cmd is hio_uch_t* */
HIO_DEV_PRO_SHELL = (1 << 13),
/* perform no waitpid() on a child process upon device destruction.
@ -120,7 +121,7 @@ typedef struct hio_dev_pro_make_t hio_dev_pro_make_t;
struct hio_dev_pro_make_t
{
int flags; /**< bitwise-ORed of hio_dev_pro_make_flag_t enumerators */
const void* cmd;
const void* cmd; /* the actual type is determined by HIO_DEV_PRO_UCMD */
hio_dev_pro_on_write_t on_write; /* mandatory */
hio_dev_pro_on_read_t on_read; /* mandatory */
hio_dev_pro_on_close_t on_close; /* optional */

View File

@ -54,7 +54,7 @@ struct hio_dev_pty_t
{
HIO_DEV_HEADER;
hio_syshnd_t pfd;
hio_syshnd_t hnd;
hio_intptr_t child_pid;
int flags;
@ -65,6 +65,7 @@ struct hio_dev_pty_t
enum hio_dev_pty_make_flag_t
{
HIO_DEV_PTY_UCMD = (1 << 12), /* cmd is hio_uch_t* */
HIO_DEV_PTY_SHELL = (1 << 13),
/* perform no waitpid() on a child process upon device destruction.
* you should set this flag if your application has automatic child
@ -79,7 +80,7 @@ typedef struct hio_dev_pty_make_t hio_dev_pty_make_t;
struct hio_dev_pty_make_t
{
int flags; /**< bitwise-ORed of hio_dev_pty_make_flag_t enumerators */
const void* cmd;
const void* cmd; /* the actual type is determined by HIO_DEV_PTY_UCMD */
hio_dev_pty_on_write_t on_write; /* mandatory */
hio_dev_pty_on_read_t on_read; /* mandatory */
@ -107,14 +108,16 @@ HIO_EXPORT hio_dev_pty_t* hio_dev_pty_make (
#if defined(HIO_HAVE_INLINE)
static HIO_INLINE hio_t* hio_dev_pty_gethio (hio_dev_pty_t* pty) { return hio_dev_gethio((hio_dev_t*)pty); }
static HIO_INLINE void* hio_dev_pty_getxtn (hio_dev_pty_t* pty) { return (void*)(pty + 1); }
static HIO_INLINE hio_syshnd_t hio_dev_pty_getsyshnd (hio_dev_pty_t* pty) { return pty->hnd; }
#else
# define hio_dev_pty_gethio(pty) hio_dev_gethio(pty)
# define hio_dev_pty_getxtn(pty) ((void*)(((hio_dev_pty_t*)pty) + 1))
# define hio_dev_pty_getsyshnd(pty) (((hio_dev_pty_t*)pty)->hnd)
#endif
#if defined(HIO_HAVE_INLINE)
static HIO_INLINE void* hio_dev_pty_getxtn (hio_dev_pty_t* pty) { return (void*)(pty + 1); }
#else
# define hio_dev_pty_getxtn(pty) ((void*)(((hio_dev_pty_t*)pty) + 1))
#endif
HIO_EXPORT void hio_dev_pty_kill (

150
hio/lib/hio-shw.h Normal file
View File

@ -0,0 +1,150 @@
/*
Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must repipeduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PIPEVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PIPECUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PIPEFITS; 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.
*/
#ifndef _HIO_SHW_H_
#define _HIO_SHW_H_
/* system handle wrapper -
* turn a raw system handle/file descript to a device object
*/
#include <hio.h>
typedef struct hio_dev_shw_t hio_dev_shw_t;
typedef int (*hio_dev_shw_on_ready_t) (
hio_dev_shw_t* dev,
int events
);
typedef int (*hio_dev_shw_on_read_t) (
hio_dev_shw_t* dev,
const void* data,
hio_iolen_t len
);
typedef int (*hio_dev_shw_on_write_t) (
hio_dev_shw_t* dev,
hio_iolen_t wrlen,
void* wrctx
);
typedef void (*hio_dev_shw_on_close_t) (
hio_dev_shw_t* dev
);
struct hio_dev_shw_t
{
HIO_DEV_HEADER;
hio_syshnd_t hnd;
int flags;
hio_dev_shw_on_ready_t on_ready;
hio_dev_shw_on_read_t on_read;
hio_dev_shw_on_write_t on_write;
hio_dev_shw_on_close_t on_close;
};
enum hio_dev_shw_make_flag_t
{
HIO_DEV_SHW_KEEP_OPEN_ON_CLOSE = (1 << 0),
HIO_DEV_SHW_DISABLE_OUT = (1 << 1),
HIO_DEV_SHW_DISABLE_IN = (1 << 2),
HIO_DEV_SHW_DISABLE_STREAM = (1 << 3)
};
typedef enum hio_dev_shw_make_flag_t hio_dev_shw_make_flag_t;
typedef struct hio_dev_shw_make_t hio_dev_shw_make_t;
struct hio_dev_shw_make_t
{
hio_syshnd_t hnd;
int flags; /**< bitwise-ORed of hio_dev_shw_make_flag_t enumerators */
hio_dev_shw_on_write_t on_write; /* mandatory */
hio_dev_shw_on_read_t on_read; /* mandatory */
hio_dev_shw_on_close_t on_close; /* optional */
hio_dev_shw_on_ready_t on_ready; /* optional */
};
#if defined(__cplusplus)
extern "C" {
#endif
HIO_EXPORT hio_dev_shw_t* hio_dev_shw_make (
hio_t* hio,
hio_oow_t xtnsize,
const hio_dev_shw_make_t* data
);
#if defined(HIO_HAVE_INLINE)
static HIO_INLINE hio_t* hio_dev_shw_gethio (hio_dev_shw_t* shw) { return hio_dev_gethio((hio_dev_t*)shw); }
static HIO_INLINE void* hio_dev_shw_getxtn (hio_dev_shw_t* shw) { return (void*)(shw + 1); }
static HIO_INLINE hio_syshnd_t hio_dev_shw_getsyshnd (hio_dev_shw_t* shw) { return shw->hnd; }
#else
# define hio_dev_shw_gethio(shw) hio_dev_gethio(shw)
# define hio_dev_shw_getxtn(shw) ((void*)(((hio_dev_shw_t*)shw) + 1))
# define hio_dev_shw_getsyshnd(shw) (((hio_dev_shw_t*)shw)->hnd)
#endif
HIO_EXPORT void hio_dev_shw_kill (
hio_dev_shw_t* shw
);
HIO_EXPORT void hio_dev_shw_halt (
hio_dev_shw_t* shw
);
HIO_EXPORT int hio_dev_shw_read (
hio_dev_shw_t* shw,
int enabled
);
HIO_EXPORT int hio_dev_shw_timedread (
hio_dev_shw_t* shw,
int enabled,
const hio_ntime_t* tmout
);
HIO_EXPORT int hio_dev_shw_write (
hio_dev_shw_t* shw,
const void* data,
hio_iolen_t len,
void* wrctx
);
HIO_EXPORT int hio_dev_shw_timedwrite (
hio_dev_shw_t* shw,
const void* data,
hio_iolen_t len,
const hio_ntime_t* tmout,
void* wrctx
);
#if defined(__cplusplus)
}
#endif
#endif

View File

@ -64,7 +64,7 @@ static void free_param (hio_t* hio, param_t* param)
HIO_MEMSET (param, 0, HIO_SIZEOF(*param));
}
static int make_param (hio_t* hio, const hio_bch_t* cmd, int flags, param_t* param)
static int make_param (hio_t* hio, const void* cmd, int flags, param_t* param)
{
int fcnt = 0;
hio_bch_t* mcmd = HIO_NULL;
@ -73,7 +73,15 @@ static int make_param (hio_t* hio, const hio_bch_t* cmd, int flags, param_t* par
if (flags & HIO_DEV_PRO_SHELL)
{
mcmd = (hio_bch_t*)cmd;
if (flags & HIO_DEV_PRO_UCMD)
{
mcmd = hio_duputobcstr(hio, cmd, HIO_NULL);
if (HIO_UNLIKELY(!mcmd)) goto oops;
}
else
{
mcmd = (hio_bch_t*)cmd;
}
param->argv = param->fixed_argv;
param->argv[0] = "/bin/sh";
@ -87,7 +95,9 @@ static int make_param (hio_t* hio, const hio_bch_t* cmd, int flags, param_t* par
hio_bch_t** argv;
hio_bch_t* mcmdptr;
mcmd = hio_dupbcstr(hio, cmd, HIO_NULL);
mcmd = (flags & HIO_DEV_PRO_UCMD)?
hio_duputobcstr(hio, cmd, HIO_NULL):
hio_dupbcstr(hio, cmd, HIO_NULL);
if (HIO_UNLIKELY(!mcmd)) goto oops;
fcnt = hio_split_bcstr(mcmd, "", '\"', '\"', '\\');

View File

@ -45,6 +45,8 @@ struct param_t
hio_bch_t* mcmd;
hio_bch_t* fixed_argv[4];
hio_bch_t** argv;
hio_bch_t* fixed_env[2];
};
typedef struct param_t param_t;
@ -56,16 +58,28 @@ static void free_param (hio_t* hio, param_t* param)
HIO_MEMSET (param, 0, HIO_SIZEOF(*param));
}
static int make_param (hio_t* hio, const hio_bch_t* cmd, int flags, param_t* param)
static int make_param (hio_t* hio, const void* cmd, int flags, param_t* param)
{
int fcnt = 0;
hio_bch_t* mcmd = HIO_NULL;
HIO_MEMSET (param, 0, HIO_SIZEOF(*param));
/* TODO: make this configurable */
param->fixed_env[0] = "TERM=dumb";
param->fixed_env[1] = HIO_NULL;
if (flags & HIO_DEV_PTY_SHELL)
{
mcmd = (hio_bch_t*)cmd;
if (flags & HIO_DEV_PTY_UCMD)
{
mcmd = hio_duputobcstr(hio, cmd, HIO_NULL);
if (HIO_UNLIKELY(!mcmd)) goto oops;
}
else
{
mcmd = (hio_bch_t*)cmd;
}
param->argv = param->fixed_argv;
param->argv[0] = "/bin/sh";
@ -79,7 +93,9 @@ static int make_param (hio_t* hio, const hio_bch_t* cmd, int flags, param_t* par
hio_bch_t** argv;
hio_bch_t* mcmdptr;
mcmd = hio_dupbcstr(hio, cmd, HIO_NULL);
mcmd = (flags & HIO_DEV_PTY_UCMD)?
hio_duputobcstr(hio, cmd, HIO_NULL):
hio_dupbcstr(hio, cmd, HIO_NULL);
if (HIO_UNLIKELY(!mcmd)) goto oops;
fcnt = hio_split_bcstr(mcmd, "", '\"', '\"', '\\');
@ -149,8 +165,7 @@ static pid_t standard_fork_and_exec (hio_dev_pty_t* dev, int pfds[], hio_dev_pty
close (pfds[1]);
pfds[1] = HIO_SYSHND_INVALID;
/* TODO: pass environment like TERM */
execv (param->argv[0], param->argv);
execve (param->argv[0], param->argv, param->fixed_env);
/* if exec fails, free 'param' parameter which is an inherited pointer */
free_param (hio, param);
@ -252,7 +267,7 @@ static int dev_pty_make (hio_dev_t* dev, void* ctx)
if (hio_makesyshndasync(hio, pfds[0]) <= -1) goto oops;
rdev->pfd = pfds[0];
rdev->hnd = pfds[0];
rdev->child_pid = pid;
rdev->flags = info->flags;
rdev->dev_cap = HIO_DEV_CAP_OUT | HIO_DEV_CAP_IN | HIO_DEV_CAP_STREAM;
@ -314,10 +329,10 @@ static int dev_pty_kill (hio_dev_t* dev, int force)
if (rdev->on_close) rdev->on_close (rdev);
if (rdev->pfd != HIO_SYSHND_INVALID)
if (rdev->hnd != HIO_SYSHND_INVALID)
{
close (rdev->pfd);
rdev->pfd = HIO_SYSHND_INVALID;
close (rdev->hnd);
rdev->hnd = HIO_SYSHND_INVALID;
}
return 0;
}
@ -327,13 +342,13 @@ static int dev_pty_read (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devadd
hio_dev_pty_t* pty = (hio_dev_pty_t*)dev;
ssize_t x;
if (HIO_UNLIKELY(pty->pfd == HIO_SYSHND_INVALID))
if (HIO_UNLIKELY(pty->hnd == HIO_SYSHND_INVALID))
{
hio_seterrnum (pty->hio, HIO_EBADHND);
return -1;
}
x = read(pty->pfd, buf, *len);
x = read(pty->hnd, buf, *len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */
@ -351,7 +366,7 @@ static int dev_pty_write (hio_dev_t* dev, const void* data, hio_iolen_t* len, co
hio_dev_pty_t* pty = (hio_dev_pty_t*)dev;
ssize_t x;
if (HIO_UNLIKELY(pty->pfd == HIO_SYSHND_INVALID))
if (HIO_UNLIKELY(pty->hnd == HIO_SYSHND_INVALID))
{
hio_seterrnum (pty->hio, HIO_EBADHND);
return -1;
@ -361,16 +376,16 @@ static int dev_pty_write (hio_dev_t* dev, const void* data, hio_iolen_t* len, co
{
/* this is an EOF indicator */
/*hio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle */
if (HIO_LIKELY(pty->pfd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */
if (HIO_LIKELY(pty->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */
{
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
close (pty->pfd);
pty->pfd = HIO_SYSHND_INVALID;
close (pty->hnd);
pty->hnd = HIO_SYSHND_INVALID;
}
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
}
x = write(pty->pfd, data, *len);
x = write(pty->hnd, data, *len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
@ -388,7 +403,7 @@ static int dev_pty_writev (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t*
hio_dev_pty_t* pty = (hio_dev_pty_t*)dev;
ssize_t x;
if (HIO_UNLIKELY(pty->pfd == HIO_SYSHND_INVALID))
if (HIO_UNLIKELY(pty->hnd == HIO_SYSHND_INVALID))
{
hio_seterrnum (pty->hio, HIO_EBADHND);
return -1;
@ -398,16 +413,16 @@ static int dev_pty_writev (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t*
{
/* this is an EOF indicator */
/*hio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle */
if (HIO_LIKELY(pty->pfd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */
if (HIO_LIKELY(pty->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the pty immediately. so close the underlying pty */
{
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
close (pty->pfd);
pty->pfd = HIO_SYSHND_INVALID;
close (pty->hnd);
pty->hnd = HIO_SYSHND_INVALID;
}
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
}
x = writev(pty->pfd, iov, *iovcnt);
x = writev(pty->hnd, iov, *iovcnt);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
@ -423,7 +438,7 @@ static int dev_pty_writev (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t*
static hio_syshnd_t dev_pty_getsyshnd (hio_dev_t* dev)
{
hio_dev_pty_t* rdev = (hio_dev_pty_t*)dev;
return rdev->pfd;
return rdev->hnd;
}
static int dev_pty_ioctl (hio_dev_t* dev, int cmd, void* arg)

287
hio/lib/shw.c Normal file
View File

@ -0,0 +1,287 @@
/*
Copyright (c) 2016-2020 Chung, Hyung-Hwan. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WAfRRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR 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.
*/
#include <hio-shw.h>
#include "hio-prv.h"
#include <unistd.h>
#include <errno.h>
#include <sys/uio.h>
static int dev_shw_make (hio_dev_t* dev, void* ctx)
{
hio_t* hio = dev->hio;
hio_dev_shw_t* rdev = (hio_dev_shw_t*)dev;
hio_dev_shw_make_t* info = (hio_dev_shw_make_t*)ctx;
rdev->hnd = info->hnd;
rdev->flags = info->flags;
rdev->dev_cap = HIO_DEV_CAP_OUT | HIO_DEV_CAP_IN | HIO_DEV_CAP_STREAM;
if (info->flags & HIO_DEV_SHW_DISABLE_OUT) rdev->dev_cap &= ~HIO_DEV_CAP_OUT;
if (info->flags & HIO_DEV_SHW_DISABLE_IN) rdev->dev_cap &= ~HIO_DEV_CAP_IN;
if (info->flags & HIO_DEV_SHW_DISABLE_STREAM) rdev->dev_cap &= ~HIO_DEV_CAP_STREAM;
rdev->on_ready = info->on_ready;
rdev->on_read = info->on_read;
rdev->on_write = info->on_write;
rdev->on_close = info->on_close;
return 0;
oops:
/* don't close the handle regardless of HIO_DEV_SHW_KEEP_OPEN_ON_CLOSE.
* the device is not created. so no ownership of the handle is passed to this wrapper device */
return -1;
}
static int dev_shw_kill (hio_dev_t* dev, int force)
{
hio_t* hio = dev->hio;
hio_dev_shw_t* rdev = (hio_dev_shw_t*)dev;
if (rdev->on_close) rdev->on_close (rdev);
if (rdev->hnd != HIO_SYSHND_INVALID)
{
if (!(rdev->flags & HIO_DEV_SHW_KEEP_OPEN_ON_CLOSE))
{
close (rdev->hnd);
rdev->hnd = HIO_SYSHND_INVALID;
}
}
return 0;
}
static int dev_shw_read (hio_dev_t* dev, void* buf, hio_iolen_t* len, hio_devaddr_t* srcaddr)
{
hio_dev_shw_t* shw = (hio_dev_shw_t*)dev;
ssize_t x;
if (HIO_UNLIKELY(shw->hnd == HIO_SYSHND_INVALID))
{
hio_seterrnum (shw->hio, HIO_EBADHND);
return -1;
}
x = read(shw->hnd, buf, *len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data available */
if (errno == EINTR) return 0;
hio_seterrwithsyserr (shw->hio, 0, errno);
return -1;
}
*len = x;
return 1;
}
static int dev_shw_write (hio_dev_t* dev, const void* data, hio_iolen_t* len, const hio_devaddr_t* dstaddr)
{
hio_dev_shw_t* shw = (hio_dev_shw_t*)dev;
ssize_t x;
if (HIO_UNLIKELY(shw->hnd == HIO_SYSHND_INVALID))
{
hio_seterrnum (shw->hio, HIO_EBADHND);
return -1;
}
if (HIO_UNLIKELY(*len <= 0))
{
/* this is an EOF indicator */
/*hio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle */
if (HIO_LIKELY(shw->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the handle immediately. so close the underlying handle */
{
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
if (!(shw->flags & HIO_DEV_SHW_KEEP_OPEN_ON_CLOSE))
{
close (shw->hnd);
shw->hnd = HIO_SYSHND_INVALID;
}
}
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
}
x = write(shw->hnd, data, *len);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0;
hio_seterrwithsyserr (shw->hio, 0, errno);
return -1;
}
*len = x;
return 1;
}
static int dev_shw_writev (hio_dev_t* dev, const hio_iovec_t* iov, hio_iolen_t* iovcnt, const hio_devaddr_t* dstaddr)
{
hio_dev_shw_t* shw = (hio_dev_shw_t*)dev;
ssize_t x;
if (HIO_UNLIKELY(shw->hnd == HIO_SYSHND_INVALID))
{
hio_seterrnum (shw->hio, HIO_EBADHND);
return -1;
}
if (HIO_UNLIKELY(*iovcnt <= 0))
{
/* this is an EOF indicator */
/*hio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle */
if (HIO_LIKELY(shw->hnd != HIO_SYSHND_INVALID)) /* halt() doesn't close the handle immediately. so close the underlying handle */
{
hio_dev_watch (dev, HIO_DEV_WATCH_STOP, 0);
if (!(shw->flags & HIO_DEV_SHW_KEEP_OPEN_ON_CLOSE))
{
close (shw->hnd);
shw->hnd = HIO_SYSHND_INVALID;
}
}
return 1; /* indicate that the operation got successful. the core will execute on_write() with 0. */
}
x = writev(shw->hnd, iov, *iovcnt);
if (x <= -1)
{
if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) return 0; /* no data can be written */
if (errno == EINTR) return 0;
hio_seterrwithsyserr (shw->hio, 0, errno);
return -1;
}
*iovcnt = x;
return 1;
}
static hio_syshnd_t dev_shw_getsyshnd (hio_dev_t* dev)
{
hio_dev_shw_t* rdev = (hio_dev_shw_t*)dev;
return rdev->hnd;
}
static hio_dev_mth_t dev_shw_methods =
{
dev_shw_make,
dev_shw_kill,
HIO_NULL,
dev_shw_getsyshnd,
HIO_NULL,
HIO_NULL, /* ioctl */
dev_shw_read,
dev_shw_write,
dev_shw_writev,
HIO_NULL, /* sendfile */
};
/* ========================================================================= */
static int shw_ready (hio_dev_t* dev, int events)
{
hio_t* hio = dev->hio;
hio_dev_shw_t* shw = (hio_dev_shw_t*)dev;
if (events & HIO_DEV_EVENT_ERR)
{
hio_seterrnum (hio, HIO_EDEVERR);
return -1;
}
if (events & HIO_DEV_EVENT_HUP)
{
if (events & (HIO_DEV_EVENT_PRI | HIO_DEV_EVENT_IN | HIO_DEV_EVENT_OUT))
{
/* probably half-open? */
return shw->on_ready? shw->on_ready(shw, events): 1;
}
hio_seterrnum (hio, HIO_EDEVHUP);
return -1;
}
/* 1 - the device is ok. carry on reading or writing */
return shw->on_ready? shw->on_ready(shw, events): 1;
}
static int shw_on_read (hio_dev_t* dev, const void* data, hio_iolen_t len, const hio_devaddr_t* srcaddr)
{
hio_dev_shw_t* shw = (hio_dev_shw_t*)dev;
return shw->on_read(shw, data, len);
}
static int shw_on_write (hio_dev_t* dev, hio_iolen_t wrlen, void* wrctx, const hio_devaddr_t* dstaddr)
{
hio_dev_shw_t* shw = (hio_dev_shw_t*)dev;
return shw->on_write(shw, wrlen, wrctx);
}
static hio_dev_evcb_t dev_shw_event_callbacks =
{
shw_ready,
shw_on_read,
shw_on_write
};
/* ========================================================================= */
hio_dev_shw_t* hio_dev_shw_make (hio_t* hio, hio_oow_t xtnsize, const hio_dev_shw_make_t* info)
{
return (hio_dev_shw_t*)hio_dev_make(
hio, HIO_SIZEOF(hio_dev_shw_t) + xtnsize,
&dev_shw_methods, &dev_shw_event_callbacks, (void*)info);
}
void hio_dev_shw_kill (hio_dev_shw_t* dev)
{
hio_dev_kill ((hio_dev_t*)dev);
}
void hio_dev_shw_halt (hio_dev_shw_t* dev)
{
hio_dev_halt ((hio_dev_t*)dev);
}
int hio_dev_shw_read (hio_dev_shw_t* dev, int enabled)
{
return hio_dev_read((hio_dev_t*)dev, enabled);
}
int hio_dev_shw_timedread (hio_dev_shw_t* dev, int enabled, const hio_ntime_t* tmout)
{
return hio_dev_timedread((hio_dev_t*)dev, enabled, tmout);
}
int hio_dev_shw_write (hio_dev_shw_t* dev, const void* data, hio_iolen_t dlen, void* wrctx)
{
return hio_dev_write((hio_dev_t*)dev, data, dlen, wrctx, HIO_NULL);
}
int hio_dev_shw_timedwrite (hio_dev_shw_t* dev, const void* data, hio_iolen_t dlen, const hio_ntime_t* tmout, void* wrctx)
{
return hio_dev_timedwrite((hio_dev_t*)dev, data, dlen, tmout, wrctx, HIO_NULL);
}