diff --git a/stio/lib/stio-pro.c b/stio/lib/stio-pro.c index b8cbd5a..ef3f765 100644 --- a/stio/lib/stio-pro.c +++ b/stio/lib/stio-pro.c @@ -31,16 +31,107 @@ #include #include -static int pro_make (stio_dev_t* dev, void* ctx) -{ - stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; - stio_dev_pro_make_t* arg = (stio_dev_pro_make_t*)ctx; - stio_syshnd_t hnd[6]; - int i, minidx = -1, maxidx = -1; - if (arg->flags & STIO_DEV_PRO_WRITEIN) +static stio_dev_pro_t* make_sibling (stio_t* stio, stio_syshnd_t handle); + +/* ========================================================================= */ + +static pid_t standard_fork_and_exec (stio_dev_pro_t* rdev, int pfds[], stio_dev_pro_make_t* info) +{ + pid_t pid; + + pid = fork (); + if (fork() == -1) { - if (pipe(&hnd[0]) == -1) + rdev->stio->errnum = stio_syserrtoerrnum(errno); + return -1; + } + + if (pid == 0) + { + stio_syshnd_t devnull = STIO_SYSHND_INVALID; + + /* TODO: close all uneeded fds */ + if (info->flags & STIO_DEV_PRO_WRITEIN) + { + /* child should read */ + close (pfds[1]); + pfds[1] = STIO_SYSHND_INVALID; + + /* let the pipe be standard input */ + if (dup2 (pfds[0], 0) <= -1) goto child_oops; + + close (pfds[0]); + pfds[0] = STIO_SYSHND_INVALID; + } + + if (info->flags & STIO_DEV_PRO_READOUT) + { + /* child should write */ + close (pfds[2]); + pfds[2] = STIO_SYSHND_INVALID; + + if (dup2(pfds[3], 1) == -1) goto child_oops; + + if (info->flags & STIO_DEV_PRO_ERRTOOUT) + { + if (dup2(pfds[3], 2) == -1) goto child_oops; + } + + close (pfds[3]); + pfds[3] = STIO_SYSHND_INVALID; + } + + if (info->flags & STIO_DEV_PRO_READERR) + { + close (pfds[4]); + pfds[4] = STIO_SYSHND_INVALID; + + if (dup2(pfds[5], 2) == -1) goto child_oops; + + if (info->flags & STIO_DEV_PRO_OUTTOERR) + { + if (dup2(pfds[5], 1) == -1) goto child_oops; + } + + close (pfds[5]); + pfds[5] = STIO_SYSHND_INVALID; + } + + if ((info->flags & STIO_DEV_PRO_INTONUL) || + (info->flags & STIO_DEV_PRO_OUTTONUL) || + (info->flags & STIO_DEV_PRO_ERRTONUL)) + { + #if defined(O_LARGEFILE) + devnull = open ("/dev/null", O_RDWR | O_LARGEFILE, 0); + #else + devnull = open ("/dev/null", O_RDWR, 0); + #endif + if (devnull == STIO_SYSHND_INVALID) goto child_oops; + } + + //execv (param->argv[0], param->argv); + + child_oops: + if (devnull != STIO_SYSHND_INVALID) close(devnull); + _exit (128); + } + + return pid; + +} + +static int dev_pro_make (stio_dev_t* dev, void* ctx) +{ + stio_dev_pro_t* rdev = (stio_dev_pro_t*)dev; + stio_dev_pro_make_t* info = (stio_dev_pro_make_t*)ctx; + stio_syshnd_t pfds[6]; + int i, minidx = -1, maxidx = -1; + pid_t pid; + + if (info->flags & STIO_DEV_PRO_WRITEIN) + { + if (pipe(&pfds[0]) == -1) { dev->stio->errnum = stio_syserrtoerrnum(errno); goto oops; @@ -48,9 +139,9 @@ static int pro_make (stio_dev_t* dev, void* ctx) minidx = 0; maxidx = 1; } - if (arg->flags & STIO_DEV_PRO_READOUT) + if (info->flags & STIO_DEV_PRO_READOUT) { - if (pipe(&hnd[2]) == -1) + if (pipe(&pfds[2]) == -1) { dev->stio->errnum = stio_syserrtoerrnum(errno); goto oops; @@ -59,9 +150,9 @@ static int pro_make (stio_dev_t* dev, void* ctx) maxidx = 3; } - if (arg->flags & STIO_DEV_PRO_READERR) + if (info->flags & STIO_DEV_PRO_READERR) { - if (pipe(&hnd[4]) == -1) + if (pipe(&pfds[4]) == -1) { dev->stio->errnum = stio_syserrtoerrnum(errno); goto oops; @@ -76,9 +167,14 @@ static int pro_make (stio_dev_t* dev, void* ctx) goto oops; } - /* TODO: fork and exec... */ +/* TODO: more advanced fork and exec .. */ + pid = standard_fork_and_exec (rdev, pfds, info); + if (pid <= -1) goto oops; - if (arg->flags & STIO_DEV_PRO_WRITEIN) + rdev->child_pid = pid; + + /* this is the parent process */ + if (info->flags & STIO_DEV_PRO_WRITEIN) { /* * 012345 @@ -86,11 +182,11 @@ static int pro_make (stio_dev_t* dev, void* ctx) * X * WRITE => 1 */ - close (hnd[0]); - hnd[0] = STIO_SYSHND_INVALID; + close (pfds[0]); + pfds[0] = STIO_SYSHND_INVALID; } - if (arg->flags & STIO_DEV_PRO_READOUT) + if (info->flags & STIO_DEV_PRO_READOUT) { /* * 012345 @@ -98,11 +194,11 @@ static int pro_make (stio_dev_t* dev, void* ctx) * X * READ => 2 */ - close (hnd[3]); - hnd[3] = STIO_SYSHND_INVALID; + close (pfds[3]); + pfds[3] = STIO_SYSHND_INVALID; } - if (arg->flags & STIO_DEV_PRO_READERR) + if (info->flags & STIO_DEV_PRO_READERR) { /* * 012345 @@ -110,31 +206,84 @@ static int pro_make (stio_dev_t* dev, void* ctx) * X * READ => 4 */ - close (hnd[5]); - hnd[5] = STIO_SYSHND_INVALID; + close (pfds[5]); + pfds[5] = STIO_SYSHND_INVALID; } - if (stio_makesyshndasync (pro->stio, hnd[1]) <= -1 || - stio_makesyshndasync (pro->stio, hnd[2]) <= -1 || - stio_makesyshndasync (pro->stio, hnd[4]) <= -1) goto oops; + if (stio_makesyshndasync (dev->stio, pfds[1]) <= -1 || + stio_makesyshndasync (dev->stio, pfds[2]) <= -1 || + stio_makesyshndasync (dev->stio, pfds[4]) <= -1) goto oops; + if (pfds[2] != STIO_SYSHND_INVALID) + { + rdev->sibling[0] = make_sibling (dev->stio, pfds[2]); + if (!rdev->sibling[0]) goto oops; + pfds[2] = STIO_SYSHND_INVALID; + } + + if (pfds[4] != STIO_SYSHND_INVALID) + { + rdev->sibling[1] = make_sibling (dev->stio, pfds[4]); + if (!rdev->sibling[1]) + { + if (rdev->sibling[0]) + { + stio_dev_pro_kill (rdev->sibling[0]); + rdev->sibling[0] = STIO_NULL; + } + goto oops; + } + pfds[4] = STIO_SYSHND_INVALID; + } + + rdev->pfd = pfds[1]; return 0; oops: for (i = minidx; i < maxidx; i++) { - if (hnd[i] != STIO_SYSHND_INVALID) close (hnd[i]); + if (pfds[i] != STIO_SYSHND_INVALID) close (pfds[i]); } return -1; } - -static void pro_kill (stio_dev_t* dev) +static int dev_pro_make_sibling (stio_dev_t* dev, void* ctx) { + stio_dev_pro_t* rdev = (stio_dev_pro_t*)dev; + stio_syshnd_t* handle = (stio_syshnd_t*)ctx; + + rdev->pfd = *handle; + if (stio_makesyshndasync (rdev->stio, rdev->pfd) <= -1) return -1; + + return 0; } -static int pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len) + +static void dev_pro_kill (stio_dev_t* dev) +{ + stio_dev_pro_t* rdev = (stio_dev_pro_t*)dev; + + if (rdev->pfd != STIO_SYSHND_INVALID) + { + close (rdev->pfd); + rdev->pfd = STIO_SYSHND_INVALID; + } + + if (rdev->sibling[0]) + { + stio_dev_pro_kill (rdev->sibling[0]); + rdev->sibling[0] = STIO_NULL; + } + + if (rdev->sibling[1]) + { + stio_dev_pro_kill (rdev->sibling[1]); + rdev->sibling[1] = STIO_NULL; + } +} + +static int dev_pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len, stio_devadr_t* srcadr) { stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; ssize_t x; @@ -152,33 +301,61 @@ static int pro_read (stio_dev_t* dev, void* buf, stio_iolen_t* len) return 1; } -static int pro_write (stio_dev_t* dev, const void* data, stio_iolen_t* len) +static int dev_pro_write (stio_dev_t* dev, const void* data, stio_iolen_t* len, const stio_devadr_t* dstadr) { return -1; } -static stio_syshnd_t pro_getsyshnd (stio_dev_t* dev) +static stio_syshnd_t dev_pro_getsyshnd (stio_dev_t* dev) { stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; return (stio_syshnd_t)pro->pfd; } -static int pro_ioctl (stio_dev_t* dev, int cmd, void* arg) +static int dev_pro_ioctl (stio_dev_t* dev, int cmd, void* arg) { + +/* + switch (cmd) + { + case STIO_DEV_PRO_KILL + case STIO_DEV_PRO_CLOSEIN: + case STIO_DEV_PRO_CLOSEOUT: + case STIO_DEV_PROC_CLOSEERR: + } +*/ + return 0; } -static stio_dev_mth_t pro_mth = +static stio_dev_mth_t dev_pro_methods = { - pro_make, - pro_kill, - pro_getsyshnd, - pro_read, - pro_write, - pro_ioctl + dev_pro_make, + dev_pro_kill, + dev_pro_getsyshnd, + + dev_pro_read, + dev_pro_write, + dev_pro_ioctl }; + + +static stio_dev_mth_t dev_pro_methods_sibling = +{ + dev_pro_make_sibling, + dev_pro_kill, + dev_pro_getsyshnd, + + dev_pro_read, + dev_pro_write, + dev_pro_ioctl +}; + +/* ========================================================================= */ + + static int pro_ready (stio_dev_t* dev, int events) { stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; @@ -211,22 +388,35 @@ static int pro_on_read (stio_dev_t* dev, const void* data, stio_iolen_t len, con return pro->on_read (pro, data, len); } -static int pro_on_write (stio_dev_t* dev, void* wrctx, const stio_devadr_t* dstadr) +static int pro_on_write (stio_dev_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_devadr_t* dstadr) { stio_dev_pro_t* pro = (stio_dev_pro_t*)dev; return pro->on_write (pro, wrctx); } -static stio_dev_evcb_t pro_evcb = +static stio_dev_evcb_t dev_pro_event_callbacks = { pro_ready, pro_on_read, pro_on_write }; + +/* ========================================================================= */ + +static stio_dev_pro_t* make_sibling (stio_t* stio, stio_syshnd_t handle) +{ + return (stio_dev_pro_t*)stio_makedev ( + stio, STIO_SIZEOF(stio_dev_pro_t), + &dev_pro_methods_sibling, &dev_pro_event_callbacks, (void*)&handle); + +} + stio_dev_pro_t* stio_dev_pro_make (stio_t* stio, stio_size_t xtnsize, const stio_dev_pro_make_t* data) { - return (stio_dev_pro_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_pro_t) + xtnsize, &pro_mth, &pro_evcb, (void*)data); + return (stio_dev_pro_t*)stio_makedev ( + stio, STIO_SIZEOF(stio_dev_pro_t) + xtnsize, + &dev_pro_methods, &dev_pro_event_callbacks, (void*)data); } void stio_dev_pro_kill (stio_dev_pro_t* pro) @@ -258,4 +448,5 @@ stio_dev_pro_t* stio_dev_pro_getdev (stio_dev_pro_t* pro, stio_dev_pro_type_t ty pro->dev->stio = STIO_EINVAL; return STIO_NULL; } + #endif diff --git a/stio/lib/stio-pro.h b/stio/lib/stio-pro.h index 3a5d107..a6d8fcc 100644 --- a/stio/lib/stio-pro.h +++ b/stio/lib/stio-pro.h @@ -48,10 +48,10 @@ struct stio_dev_pro_t STIO_DEV_HEADERS; stio_syshnd_t pfd; - - /* bitwised-ORed of #stio_dev_pro_state_t enumerators */ stio_dev_pro_type_t type; + stio_intptr_t child_pid; + stio_dev_pro_t* sibling[2]; stio_dev_pro_on_read_t on_read; @@ -65,12 +65,17 @@ enum stio_dev_pro_make_flag_t STIO_DEV_PRO_WRITEIN = (1 << 0), STIO_DEV_PRO_READOUT = (1 << 1), STIO_DEV_PRO_READERR = (1 << 2), - STIO_DEV_PRO_INTONUL = (1 << 3), - STIO_DEV_PRO_OUTTONUL = (1 << 4), - STIO_DEV_PRO_ERRTONUL = (1 << 5), - STUO_DEV_PRO_DROPIN = (1 << 6), - STUO_DEV_PRO_DROPOUT = (1 << 7), - STUO_DEV_PRO_DROPERR = (1 << 8) + + STIO_DEV_PRO_ERRTOOUT = (1 << 3), + STIO_DEV_PRO_OUTTOERR = (1 << 4), + + STIO_DEV_PRO_INTONUL = (1 << 5), + STIO_DEV_PRO_OUTTONUL = (1 << 6), + STIO_DEV_PRO_ERRTONUL = (1 << 7), + + STUO_DEV_PRO_DROPIN = (1 << 8), + STUO_DEV_PRO_DROPOUT = (1 << 9), + STUO_DEV_PRO_DROPERR = (1 << 10) }; typedef enum stio_dev_pro_make_flag_t stio_dev_pro_make_flag_t; @@ -100,7 +105,7 @@ STIO_EXPORT void stio_dev_pro_kill ( STIO_EXPORT int stio_dev_pro_write ( stio_dev_pro_t* pro, const void* data, - stio_iolen_t len, + stio_iolen_t len, void* wrctx ); diff --git a/stio/lib/stio-sck.c b/stio/lib/stio-sck.c index dfa21db..368c97d 100644 --- a/stio/lib/stio-sck.c +++ b/stio/lib/stio-sck.c @@ -64,7 +64,7 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto) stio_sckhnd_t sck; #if defined(_WIN32) - sck = WSASocket (domain, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED /*| WSA_FLAG_NO_HANDLE_INHERIT*/); + sck = WSASocket (domain, type, proto, NULL, 0, WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT); if (sck == STIO_SCKHND_INVALID) { /* stio_seterrnum (dev->stio, STIO_ESYSERR); or translate errno to stio errnum */ @@ -78,13 +78,24 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto) return STIO_SCKHND_INVALID; } +#if defined(FD_CLOEXEC) + { + int flags = fcntl (sck, F_GETFD, 0); + if (fcntl (sck, F_SETFD, flags | FD_CLOEXEC) == -1) + { + stio->errnum = stio_syserrtoerrnum(errno); + return STIO_SCKHND_INVALID; + } + } +#endif + if (stio_makesckasync (stio, sck) <= -1) { close (sck); return STIO_SCKHND_INVALID; } - /* TODO: set CLOEXEC if it's defined */ + #endif return sck; @@ -536,7 +547,7 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg) return 0; } -static stio_dev_mth_t dev_mth_sck_stateless = +static stio_dev_mth_t dev_sck_methods_stateless = { dev_sck_make, dev_sck_kill, @@ -548,7 +559,7 @@ static stio_dev_mth_t dev_mth_sck_stateless = }; -static stio_dev_mth_t dev_mth_sck_stateful = +static stio_dev_mth_t dev_sck_methods_stateful = { dev_sck_make, dev_sck_kill, @@ -791,14 +802,14 @@ static int dev_evcb_sck_on_write_stateless (stio_dev_t* dev, stio_iolen_t wrlen, return rdev->on_write (rdev, wrlen, wrctx, dstadr->ptr); } -static stio_dev_evcb_t dev_evcb_sck_stateful = +static stio_dev_evcb_t dev_sck_event_callbacks_stateful = { dev_evcb_sck_ready_stateful, dev_evcb_sck_on_read_stateful, dev_evcb_sck_on_write_stateful }; -static stio_dev_evcb_t dev_evcb_sck_stateless = +static stio_dev_evcb_t dev_sck_event_callbacks_stateless = { dev_evcb_sck_ready_stateless, dev_evcb_sck_on_read_stateless, @@ -819,11 +830,15 @@ stio_dev_sck_t* stio_dev_sck_make (stio_t* stio, stio_size_t xtnsize, const stio if (sck_type_map[info->type].extra_dev_capa & STIO_DEV_CAPA_STREAM) /* can't use the IS_STATEFUL() macro yet */ { - rdev = (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck_stateful, &dev_evcb_sck_stateful, (void*)info); + rdev = (stio_dev_sck_t*)stio_makedev ( + stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, + &dev_sck_methods_stateful, &dev_sck_event_callbacks_stateful, (void*)info); } else { - rdev = (stio_dev_sck_t*)stio_makedev (stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, &dev_mth_sck_stateless, &dev_evcb_sck_stateless, (void*)info); + rdev = (stio_dev_sck_t*)stio_makedev ( + stio, STIO_SIZEOF(stio_dev_sck_t) + xtnsize, + &dev_sck_methods_stateless, &dev_sck_event_callbacks_stateless, (void*)info); } return rdev; diff --git a/stio/lib/stio-sck.h b/stio/lib/stio-sck.h index 69cdd1b..f8538ff 100644 --- a/stio/lib/stio-sck.h +++ b/stio/lib/stio-sck.h @@ -286,7 +286,7 @@ STIO_EXPORT int stio_dev_sck_listen ( STIO_EXPORT int stio_dev_sck_write ( stio_dev_sck_t* dev, const void* data, - stio_iolen_t len, + stio_iolen_t len, void* wrctx, const stio_sckadr_t* dstadr ); @@ -294,7 +294,7 @@ STIO_EXPORT int stio_dev_sck_write ( STIO_EXPORT int stio_dev_sck_timedwrite ( stio_dev_sck_t* dev, const void* data, - stio_iolen_t len, + stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx, const stio_sckadr_t* dstadr @@ -313,28 +313,10 @@ static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled) return stio_dev_read ((stio_dev_t*)sck, enabled); } -/* -static STIO_INLINE int stio_dev_sck_write (stio_dev_sck_t* sck, const void* data, stio_iolen_t len, void* wrctx, const stio_devadr_t* dstadr) -{ - return stio_dev_write ((stio_dev_t*)sck, data, len, wrctx, STIO_NULL); -} - -static STIO_INLINE int stio_dev_sck_timedwrite (stio_dev_sck_t* sck, const void* data, stio_iolen_t len, const stio_ntime_t* tmout, void* wrctx) -{ - return stio_dev_timedwrite ((stio_dev_t*)sck, data, len, tmout, wrctx, STIO_NULL); -} -*/ - - #else #define stio_dev_sck_halt(sck) stio_dev_halt((stio_dev_t*)sck) #define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled) -/* -#define stio_dev_sck_write(sck,data,len,wrctx) stio_dev_write((stio_dev_t*)sck, data, len, wrctx, STIO_NULL) -#define stio_dev_sck_timedwrite(sck,data,len,tmout,wrctx) stio_dev_timedwrite((stio_dev_t*)sck, data, len, tmout, wrctx, STIO_NULL) -*/ - #endif