diff --git a/hio/lib/Makefile.am b/hio/lib/Makefile.am index b9a0343..26f19db 100644 --- a/hio/lib/Makefile.am +++ b/hio/lib/Makefile.am @@ -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 \ diff --git a/hio/lib/Makefile.in b/hio/lib/Makefile.in index 90c885c..286e664 100644 --- a/hio/lib/Makefile.in +++ b/hio/lib/Makefile.in @@ -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 diff --git a/hio/lib/hio-pro.h b/hio/lib/hio-pro.h index 7b5e190..b78b990 100644 --- a/hio/lib/hio-pro.h +++ b/hio/lib/hio-pro.h @@ -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 */ diff --git a/hio/lib/hio-pty.h b/hio/lib/hio-pty.h index 9b78c88..5f4696e 100644 --- a/hio/lib/hio-pty.h +++ b/hio/lib/hio-pty.h @@ -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 ( diff --git a/hio/lib/hio-shw.h b/hio/lib/hio-shw.h new file mode 100644 index 0000000..a386732 --- /dev/null +++ b/hio/lib/hio-shw.h @@ -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 + +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 diff --git a/hio/lib/pro.c b/hio/lib/pro.c index d0d00dd..d4f49af 100644 --- a/hio/lib/pro.c +++ b/hio/lib/pro.c @@ -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, "", '\"', '\"', '\\'); diff --git a/hio/lib/pty.c b/hio/lib/pty.c index b305b9d..ea2dc15 100644 --- a/hio/lib/pty.c +++ b/hio/lib/pty.c @@ -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) diff --git a/hio/lib/shw.c b/hio/lib/shw.c new file mode 100644 index 0000000..bb10e95 --- /dev/null +++ b/hio/lib/shw.c @@ -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 +#include "hio-prv.h" + +#include +#include +#include + +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); +}