diff options
author | midipix <writeonce@midipix.org> | 2022-10-24 01:33:09 +0000 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2022-10-30 16:24:17 +0000 |
commit | b824c9188a7636b0f8b483ac1ade79885610cca1 (patch) | |
tree | 85f91fbac5cfad0bd7b742ee8a2b727bdfe9d7ac /src/cmds | |
parent | 6dc70d02aa1767532f0339e7e335d544edced1c8 (diff) | |
download | ntux-b824c9188a7636b0f8b483ac1ade79885610cca1.tar.bz2 ntux-b824c9188a7636b0f8b483ac1ade79885610cca1.tar.xz |
ntux_cmd_bridge(): initial implementation and integration.
Diffstat (limited to 'src/cmds')
-rw-r--r-- | src/cmds/ntux_cmd_bridge.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/src/cmds/ntux_cmd_bridge.c b/src/cmds/ntux_cmd_bridge.c new file mode 100644 index 0000000..e187f11 --- /dev/null +++ b/src/cmds/ntux_cmd_bridge.c @@ -0,0 +1,202 @@ +/***********************************************************/ +/* ntux: native translation und extension */ +/* Copyright (C) 2016--2022 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.NTUX. */ +/***********************************************************/ + +#include <ntapi/nt_termios.h> + +#include <psxabi/sys_sysapi.h> +#include <psxabi/sys_fcntl.h> +#include <psxabi/sys_errno.h> +#include <psxabi/sys_process.h> +#include <psxxfi/xfi_framework.h> + +#include <ntux/ntux.h> +#include "ntux_driver_impl.h" +#include "ntux_nolibc_impl.h" +#include "ntux_errinfo_impl.h" + +int ntux_cmd_bridge(const struct ntux_driver_ctx * dctx) +{ + int ret; + int val; + pid_t pid; + int argc; + const char ** argv; + const char ** envp; + unsigned char * program; + unsigned char * logfile; + ssize_t rbytes; + ssize_t wbytes; + char * ch; + char * script; + char * interp; + const char * usrscript; + char ** sargv; + const char ** pargv; + const char ** aargv; + char buf[2048]; + int fdlog[2]; + int32_t status; + + struct ntux_fd_ctx fdctx; + + /* init */ + ntux_driver_set_ectx( + dctx,0, + dctx->cctx->sargv[0]); + + if (ntux_get_driver_fdctx(dctx,&fdctx) < 0) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + + if (dctx->cctx->interp) { + ret = __xfi_framework_get_int32_slot_value( + PSX_RTDATA_UDAT32_ARGV1_IS_OPTARG, + &val); + + if (ret < 0) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_CUSTOM_ERROR( + dctx, + NTUX_ERR_FLOW_ERROR); + + for (sargv=dctx->cctx->sargv; *sargv; sargv++) + (void)0; + + argc = sargv - dctx->cctx->sargv; + + if (!(aargv = ntux_calloc(argc + 3,sizeof(char *)))) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + + if (!(script = ntux_calloc(1,NTUX_MAX_PATH))) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + + if (!(interp = ntux_calloc(1,NTUX_MAX_PATH))) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + + usrscript = val ? dctx->cctx->sargv[2] : dctx->cctx->sargv[1]; + + if (__sys_fs_npath(fdctx.fdcwd,usrscript,0,script,NTUX_MAX_PATH) < 0) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + + if (__sys_fs_npath(fdctx.fdcwd,dctx->cctx->interp,0,interp,NTUX_MAX_PATH) < 0) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + + if (val) { + aargv[0] = interp; + aargv[1] = dctx->cctx->sargv[1]; + aargv[2] = script; + + sargv = &dctx->cctx->sargv[3]; + pargv = &aargv[3]; + } else { + aargv[0] = interp; + aargv[1] = script; + + sargv = &dctx->cctx->sargv[2]; + pargv = &aargv[2]; + } + + for (; *sargv; ) + *pargv++ = *sargv++; + + argv = aargv; + program = (unsigned char *)interp; + } else { + argv = (const char **)dctx->cctx->sargv; + program = (unsigned char *)dctx->cctx->sargv[0]; + } + + envp = (const char **)dctx->cctx->senvp; + logfile = (unsigned char *)dctx->cctx->logfile; + + /* fdlog */ + if (logfile) { + if ((fdlog[1] = __sys_openat( + ntux_driver_fdcwd(dctx), + logfile,O_CREAT|O_TRUNC|O_WRONLY,0)) < 0) + if (ntux_errno_set(dctx,fdlog[1])) + return NTUX_SYSTEM_ERROR(dctx); + } else { + if ((ret = __sys_pipe(fdlog)) < 0) + if (ntux_errno_set(dctx,ret)) + return NTUX_SYSTEM_ERROR(dctx); + } + + /* spawn */ + pid = __sys_vfork(); + + /* failed? */ + if (pid < 0) + if (ntux_errno_set(dctx,pid)) + return NTUX_SYSTEM_ERROR(dctx); + + /* child */ + if (pid == 0) + if ((status = __sys_execve(program,argv,envp))) + if (ntux_errno_set(dctx,status)) + if (NTUX_SYSTEM_ERROR(dctx)) + __sys_exit(0); + + /* parent */ + __sys_close(fdlog[1]); + + if (dctx->cctx->logfile) { + __sys_wait4( + pid,&status, + 0,0); + + return 0; + } + + /* piped bridge output */ + rbytes = __sys_read(fdlog[0],buf,sizeof(buf)); + + while (rbytes == -EINTR) + rbytes = __sys_read(fdlog[0],buf,sizeof(buf)); + + while (rbytes > 0) { + for (ch=buf; rbytes; ch += wbytes) { + wbytes = __sys_write(2,ch,rbytes); + + while (wbytes == -EINTR) + wbytes = __sys_write(2,buf,rbytes); + + if (wbytes < 0) { + __sys_close(fdlog[0]); + ntux_errno_set(dctx,wbytes); + return NTUX_SYSTEM_ERROR(dctx); + } + + rbytes -= wbytes; + } + + rbytes = __sys_read(fdlog[0],buf,sizeof(buf)); + + while (rbytes == -EINTR) + rbytes = __sys_read(fdlog[0],buf,sizeof(buf)); + } + + __sys_close(fdlog[0]); + + if (rbytes < 0) + if (ntux_errno_set(dctx,rbytes)) + return NTUX_SYSTEM_ERROR(dctx); + + /* wait */ + struct ntux_driver_ctx_impl * ictx = ntux_get_driver_ictx(dctx); + + __sys_wait4( + pid, + &ictx->cctx.status, + 0,0); + + return 0; +} |