summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2022-10-24 01:33:09 +0000
committermidipix <writeonce@midipix.org>2022-10-30 16:24:17 +0000
commitb824c9188a7636b0f8b483ac1ade79885610cca1 (patch)
tree85f91fbac5cfad0bd7b742ee8a2b727bdfe9d7ac /src
parent6dc70d02aa1767532f0339e7e335d544edced1c8 (diff)
downloadntux-b824c9188a7636b0f8b483ac1ade79885610cca1.tar.bz2
ntux-b824c9188a7636b0f8b483ac1ade79885610cca1.tar.xz
ntux_cmd_bridge(): initial implementation and integration.
Diffstat (limited to 'src')
-rw-r--r--src/cmds/ntux_cmd_bridge.c202
-rw-r--r--src/driver/ntux_amain.c5
-rw-r--r--src/driver/ntux_driver_ctx.c160
-rw-r--r--src/internal/ntux_driver_impl.h14
-rw-r--r--src/skin/ntux_skin_bridge.c24
-rw-r--r--src/skin/ntux_skin_default.c2
6 files changed, 395 insertions, 12 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;
+}
diff --git a/src/driver/ntux_amain.c b/src/driver/ntux_amain.c
index d103046..a18d67e 100644
--- a/src/driver/ntux_amain.c
+++ b/src/driver/ntux_amain.c
@@ -105,6 +105,11 @@ int ntux_main(char ** argv, char ** envp, const struct ntux_fd_ctx * fdctx)
__xfi_exit(dctx->cctx->status);
}
+ if (dctx->cctx->cmd == NTUX_CMD_BRIDGE) {
+ ntux_cmd_bridge(dctx);
+ __xfi_exit(dctx->cctx->status);
+ }
+
for (unit=dctx->units; *unit; unit++)
ntux_perform_unit_actions(dctx,*unit);
diff --git a/src/driver/ntux_driver_ctx.c b/src/driver/ntux_driver_ctx.c
index 129992c..09d2142 100644
--- a/src/driver/ntux_driver_ctx.c
+++ b/src/driver/ntux_driver_ctx.c
@@ -6,10 +6,14 @@
#include <psxabi/sys_abitypes.h>
#include <psxabi/sys_fcntl.h>
+#include <psxabi/sys_process.h>
+#include <psxabi/sys_sysapi.h>
+#include <psxxfi/xfi_framework.h>
#include <psxscl/psxscl.h>
#include <ntapi/nt_tty.h>
#include <stdint.h>
+#include <stdbool.h>
#include <ntux/ntux.h>
#include "ntux_nolibc_impl.h"
@@ -36,6 +40,18 @@ static const char * const ntux_cmd_name[NTUX_CMD_CAP] = {
[NTUX_CMD_CHMOD] = "chmod",
[NTUX_CMD_ACEIT] = "aceit",
[NTUX_CMD_FSPATH] = "fspath",
+ [NTUX_CMD_BRIDGE] = "bridge",
+};
+
+/* ntux exec commands */
+static const bool const ntux_cmd_exec[NTUX_CMD_CAP] = {
+ [NTUX_CMD_STAT] = false,
+ [NTUX_CMD_SPAWN] = true,
+ [NTUX_CMD_STRACE] = true,
+ [NTUX_CMD_CHMOD] = false,
+ [NTUX_CMD_ACEIT] = false,
+ [NTUX_CMD_FSPATH] = false,
+ [NTUX_CMD_BRIDGE] = true,
};
/* ntux command options */
@@ -47,6 +63,7 @@ static const struct argv_option * ntux_cmd_options[NTUX_CMD_CAP] = {
[NTUX_CMD_CHMOD] = ntux_chmod_options,
[NTUX_CMD_ACEIT] = ntux_aceit_options,
[NTUX_CMD_FSPATH] = ntux_fspath_options,
+ [NTUX_CMD_BRIDGE] = ntux_bridge_options,
};
/* package info */
@@ -216,6 +233,9 @@ static int ntux_cctx_update(
else if (!strcmp(entry->arg,"fspath"))
cctx->cmd = NTUX_CMD_FSPATH;
+ else if (!strcmp(entry->arg,"bridge"))
+ cctx->cmd = NTUX_CMD_BRIDGE;
+
break;
case TAG_LOADER:
@@ -264,6 +284,14 @@ static int ntux_cctx_update(
cctx->drvflags |= NTUX_DRIVER_DUMP;
break;
+ case TAG_INTERP:
+ cctx->interp = entry->arg;
+ break;
+
+ case TAG_OPTARG:
+ cctx->optarg = entry->arg;
+ break;
+
case TAG_SYNTAX:
case TAG_RPATH:
case TAG_APATH:
@@ -316,6 +344,29 @@ static int ntux_get_driver_ctx_fail(struct argv_meta * meta)
return -1;
}
+static int ntux_cmd_program_is_bridge(const char * program)
+{
+ const char * slash;
+ const char * mark;
+
+ mark = (slash = strrchr(program,'/'))
+ ? ++slash : program;
+
+ if (!strcmp(mark,"ntux.bridge.exe"))
+ return true;
+
+ else if (!strcmp(mark,"ntux.bridge.exe.interp"))
+ return true;
+
+ else if (!strcmp(mark,"ntux.bridge.exe.interp.abspath"))
+ return true;
+
+ else if (!strcmp(mark,"ntux.bridge.exe.interp.cwdpath"))
+ return true;
+
+ return false;
+}
+
static int ntux_cmd_from_program(const char * program)
{
const char * dot;
@@ -332,20 +383,33 @@ static int ntux_cmd_from_program(const char * program)
else
mark = program;
- if (!strcmp(mark,"stat"))
+ if (!strcmp(mark,"stat")) {
return NTUX_CMD_STAT;
- else if (!strcmp(mark,"spawn"))
+
+ } else if (!strcmp(mark,"spawn")) {
return NTUX_CMD_SPAWN;
- else if (!strcmp(mark,"strace"))
+
+ } else if (!strcmp(mark,"strace")) {
return NTUX_CMD_STRACE;
- else if (!strcmp(mark,"chmod"))
+
+ } else if (!strcmp(mark,"chmod")) {
return NTUX_CMD_CHMOD;
- else if (!strcmp(mark,"aceit"))
+
+ } else if (!strcmp(mark,"aceit")) {
return NTUX_CMD_ACEIT;
- else if (!strcmp(mark,"fspath"))
+
+ } else if (!strcmp(mark,"fspath")) {
return NTUX_CMD_FSPATH;
- return NTUX_CMD_DEFAULT;
+ } else if (!strcmp(mark,"bridge")) {
+ return NTUX_CMD_BRIDGE;
+
+ } else if (ntux_cmd_program_is_bridge(program)) {
+ return NTUX_CMD_BRIDGE;
+
+ } else {
+ return NTUX_CMD_DEFAULT;
+ }
}
int ntux_get_driver_ctx(
@@ -355,6 +419,8 @@ int ntux_get_driver_ctx(
const struct ntux_fd_ctx * fdctx,
struct ntux_driver_ctx ** pctx)
{
+ int ret;
+ int val;
struct ntux_driver_ctx_impl * ictx;
struct ntux_common_ctx cctx;
const struct argv_option * optv[NTUX_OPTV_ELEMENTS];
@@ -367,6 +433,9 @@ int ntux_get_driver_ctx(
char * cmdmark;
char ** execargv;
char * execarg;
+ char * interp;
+ char * pathbuf;
+ size_t pathlen;
struct argv_ctx ctx = {ARGV_VERBOSITY_NONE,
ARGV_MODE_SCAN,
0,0,0,0,0,0,0};
@@ -392,6 +461,58 @@ int ntux_get_driver_ctx(
cctx.cmd = ntux_cmd_from_program(program);
cctx.drvflags = flags;
+ switch (cctx.cmd) {
+ case NTUX_CMD_BRIDGE:
+ break;
+
+ default:
+ /* potential .exe bridge setup? */
+ pathlen = ntux_strlen(argv[0]);
+
+ if (pathlen + NTUX_EXE_SUFFIX_LEN >= NTUX_MAX_PATH)
+ break;
+
+
+ /* intermediate buffers */
+ if (!(pathbuf = ntux_calloc(1,NTUX_MAX_PATH)))
+ return NTUX_ERROR;
+
+ if (!(interp = ntux_calloc(1,NTUX_MAX_PATH))) {
+ ntux_free(pathbuf);
+ return NTUX_ERROR;
+ }
+
+ /* is argv[0] a symlink to ntux's bridge symlink? */
+ ret = __sys_readlinkat(
+ fdctx->fdcwd,
+ (const unsigned char *)argv[0],
+ pathbuf,NTUX_MAX_PATH);
+
+ if ((ret > 0) && (ret < NTUX_MAX_PATH)) {
+ if (ntux_cmd_program_is_bridge(pathbuf)) {
+ ntux_strcpy(pathbuf,argv[0]);
+ ntux_strcpy(&pathbuf[pathlen],NTUX_EXE_SUFFIX);
+
+ ret = __sys_readlinkat(
+ fdctx->fdcwd,
+ (const unsigned char *)pathbuf,
+ interp,NTUX_MAX_PATH);
+
+ ntux_free(pathbuf);
+
+ if ((ret < 0) || (ret >= NTUX_MAX_PATH)) {
+ ntux_free(interp);
+ return NTUX_ERROR;
+ }
+
+ cctx.cmd = NTUX_CMD_BRIDGE;
+ cctx.interp = interp;
+ }
+ }
+
+ break;
+ }
+
/* missing arguments? */
argv_optv_init(ntux_cmd_options[cctx.cmd],optv);
@@ -488,8 +609,11 @@ int ntux_get_driver_ctx(
else if (cctx.cmd == NTUX_CMD_FSPATH)
argv_optv_init(ntux_fspath_options,optv);
- /* spawn, strace */
- if ((cctx.cmd == NTUX_CMD_SPAWN) || (cctx.cmd == NTUX_CMD_STRACE)) {
+ else if (cctx.cmd == NTUX_CMD_BRIDGE)
+ argv_optv_init(ntux_bridge_options,optv);
+
+ /* spawn, strace, bridge */
+ if (ntux_cmd_exec[cctx.cmd]) {
argv_scan(argv,optv,&ctx,0);
if (ctx.erridx && !ctx.unitidx) {
@@ -529,12 +653,22 @@ int ntux_get_driver_ctx(
return -1;
}
- /* spawn, strace: exec argv */
- if (execargv) {
+ /* spawn, strace, bridge: exec argv */
+ if (ntux_cmd_exec[cctx.cmd]) {
*execargv = execarg;
cctx.sargv = execargv;
cctx.senvp = envp;
nunits = 0;
+
+ ret = __xfi_framework_get_int32_slot_value(
+ PSX_RTDATA_UDAT32_ARGV0_IS_INTERP,
+ &val);
+
+ if (ret < 0)
+ return NTUX_ERROR;
+
+ if (val)
+ cctx.sargv--;
}
/* finalize */
@@ -548,6 +682,7 @@ int ntux_get_driver_ctx(
if (!(ictx = ntux_driver_ctx_alloc(meta,fdctx,&cctx,nunits)))
return ntux_get_driver_ctx_fail(meta);
+ ictx->interp = interp;
ictx->ctx.program = program;
ictx->ctx.cctx = &ictx->cctx;
*pctx = &ictx->ctx;
@@ -557,6 +692,9 @@ int ntux_get_driver_ctx(
static void ntux_free_driver_ctx_impl(struct ntux_driver_ctx_alloc * ictx)
{
+ if (ictx->ctx.interp)
+ ntux_free(ictx->ctx.interp);
+
argv_free(ictx->meta);
free(ictx);
}
diff --git a/src/internal/ntux_driver_impl.h b/src/internal/ntux_driver_impl.h
index 0b8ba26..c3c109c 100644
--- a/src/internal/ntux_driver_impl.h
+++ b/src/internal/ntux_driver_impl.h
@@ -20,6 +20,14 @@ extern const struct argv_option ntux_strace_options[];
extern const struct argv_option ntux_chmod_options[];
extern const struct argv_option ntux_aceit_options[];
extern const struct argv_option ntux_fspath_options[];
+extern const struct argv_option ntux_bridge_options[];
+
+/* bridge functionality */
+#define NTUX_EXE_SUFFIX ".exe"
+#define NTUX_EXE_SUFFIX_LEN (4)
+#define NTUX_MAX_PATH_UTF8 (32768 / 2 * 3)
+#define NTUX_MAX_PATH NTUX_MAX_PATH_UTF8
+
enum app_tags {
TAG_HELP,
@@ -43,6 +51,11 @@ enum app_tags {
TAG_APATH,
TAG_NPATH,
TAG_DPATH,
+ TAG_INTERP,
+ TAG_SCRIPT,
+ TAG_OPTARG,
+ TAG_CWDPATH,
+ TAG_ABSPATH,
};
struct ntux_driver_ctx_impl {
@@ -52,6 +65,7 @@ struct ntux_driver_ctx_impl {
struct __psx_context xctx;
const struct ntux_unit_ctx *euctx;
const char * eunit;
+ char * interp;
struct ntux_error_info ** errinfp;
struct ntux_error_info ** erricap;
struct ntux_error_info * erriptr[64];
diff --git a/src/skin/ntux_skin_bridge.c b/src/skin/ntux_skin_bridge.c
new file mode 100644
index 0000000..d66eac6
--- /dev/null
+++ b/src/skin/ntux_skin_bridge.c
@@ -0,0 +1,24 @@
+#include "ntux_driver_impl.h"
+#include "argv/argv.h"
+
+const struct argv_option ntux_bridge_options[] = {
+ {"version", 'v',TAG_VERSION,ARGV_OPTARG_NONE,0,0,0,
+ "show version information"},
+
+ {"help", 'h',TAG_HELP,ARGV_OPTARG_OPTIONAL,0,"short|long",0,
+ "show usage information [listing %s options only]"},
+
+ {"interp", 'i',TAG_INTERP,ARGV_OPTARG_REQUIRED,0,0,0,
+ "script interpreter to execute"},
+
+ {"script", 's',TAG_SCRIPT,ARGV_OPTARG_REQUIRED,0,0,0,
+ "script argument to be passed to interpreter"},
+
+ {"optarg", 's',TAG_OPTARG,ARGV_OPTARG_REQUIRED,0,0,0,
+ "optional argument to be passed to interpreter"},
+
+ {"logfile", 'o',TAG_LOGFILE,ARGV_OPTARG_REQUIRED,0,0,"<FILE>",
+ "write output to %s"},
+
+ {0,0,0,0,0,0,0,0}
+};
diff --git a/src/skin/ntux_skin_default.c b/src/skin/ntux_skin_default.c
index b7fabc6..8daf019 100644
--- a/src/skin/ntux_skin_default.c
+++ b/src/skin/ntux_skin_default.c
@@ -9,7 +9,7 @@ const struct argv_option ntux_default_options[] = {
"show usage information [listing %s options only]"},
{"cmd", 0,TAG_CMD,ARGV_OPTARG_REQUIRED,0,
- "stat|spawn|strace|chmod|aceit|fspath",0,
+ "stat|spawn|strace|chmod|aceit|fspath|bridge",0,
"invoke one of the following ntux commands: %s"},
{0,0,0,0,0,0,0,0}