/***********************************************************/ /* ntux: native translation und extension */ /* Copyright (C) 2016--2022 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.NTUX. */ /***********************************************************/ #include #include #include #include #include #include #include #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; }