Blame src/cmds/ntux_cmd_bridge.c

b824c9
/***********************************************************/
b824c9
/*  ntux: native translation und extension                 */
b824c9
/*  Copyright (C) 2016--2022  SysDeer Technologies, LLC    */
b824c9
/*  Released under GPLv2 and GPLv3; see COPYING.NTUX.      */
b824c9
/***********************************************************/
b824c9
b824c9
#include <ntapi/nt_termios.h>
b824c9
b824c9
#include <psxabi/sys_sysapi.h>
b824c9
#include <psxabi/sys_fcntl.h>
b824c9
#include <psxabi/sys_errno.h>
b824c9
#include <psxabi/sys_process.h>
b824c9
#include <psxxfi/xfi_framework.h>
b824c9
b824c9
#include <ntux/ntux.h>
b824c9
#include "ntux_driver_impl.h"
b824c9
#include "ntux_nolibc_impl.h"
b824c9
#include "ntux_errinfo_impl.h"
b824c9
b824c9
int ntux_cmd_bridge(const struct ntux_driver_ctx * dctx)
b824c9
{
b824c9
	int		ret;
b824c9
	int		val;
b824c9
	pid_t		pid;
b824c9
	int		argc;
b824c9
	const char **	argv;
b824c9
	const char **	envp;
b824c9
	unsigned char * program;
b824c9
	unsigned char * logfile;
b824c9
	ssize_t		rbytes;
b824c9
	ssize_t		wbytes;
b824c9
	char *		ch;
b824c9
	char *		script;
b824c9
	char *		interp;
b824c9
	const char *	usrscript;
b824c9
	char **		sargv;
b824c9
	const char **	pargv;
b824c9
	const char **	aargv;
b824c9
	char		buf[2048];
b824c9
	int		fdlog[2];
b824c9
	int32_t		status;
b824c9
b824c9
	struct ntux_fd_ctx fdctx;
b824c9
b824c9
	/* init */
b824c9
	ntux_driver_set_ectx(
b824c9
		dctx,0,
b824c9
		dctx->cctx->sargv[0]);
b824c9
b824c9
	if (ntux_get_driver_fdctx(dctx,&fdctx) < 0)
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
	if (dctx->cctx->interp) {
b824c9
		ret = __xfi_framework_get_int32_slot_value(
b824c9
			PSX_RTDATA_UDAT32_ARGV1_IS_OPTARG,
b824c9
			&val;;
b824c9
b824c9
		if (ret < 0)
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_CUSTOM_ERROR(
b824c9
					dctx,
b824c9
					NTUX_ERR_FLOW_ERROR);
b824c9
b824c9
		for (sargv=dctx->cctx->sargv; *sargv; sargv++)
b824c9
			(void)0;
b824c9
b824c9
		argc = sargv - dctx->cctx->sargv;
b824c9
b824c9
		if (!(aargv = ntux_calloc(argc + 3,sizeof(char *))))
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
		if (!(script = ntux_calloc(1,NTUX_MAX_PATH)))
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
		if (!(interp = ntux_calloc(1,NTUX_MAX_PATH)))
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
		usrscript = val ? dctx->cctx->sargv[2] : dctx->cctx->sargv[1];
b824c9
b824c9
		if (__sys_fs_npath(fdctx.fdcwd,usrscript,0,script,NTUX_MAX_PATH) < 0)
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
		if (__sys_fs_npath(fdctx.fdcwd,dctx->cctx->interp,0,interp,NTUX_MAX_PATH) < 0)
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
		if (val) {
b824c9
			aargv[0] = interp;
b824c9
			aargv[1] = dctx->cctx->sargv[1];
b824c9
			aargv[2] = script;
b824c9
b824c9
			sargv    = &dctx->cctx->sargv[3];
b824c9
			pargv    = &aargv[3];
b824c9
		} else {
b824c9
			aargv[0] = interp;
b824c9
			aargv[1] = script;
b824c9
b824c9
			sargv    = &dctx->cctx->sargv[2];
b824c9
			pargv    = &aargv[2];
b824c9
		}
b824c9
b824c9
		for (; *sargv; )
b824c9
			*pargv++ = *sargv++;
b824c9
b824c9
		argv    = aargv;
b824c9
		program = (unsigned char *)interp;
b824c9
	} else {
b824c9
		argv    = (const char **)dctx->cctx->sargv;
b824c9
		program = (unsigned char *)dctx->cctx->sargv[0];
b824c9
	}
b824c9
b824c9
	envp    = (const char **)dctx->cctx->senvp;
b824c9
	logfile = (unsigned char *)dctx->cctx->logfile;
b824c9
b824c9
	/* fdlog */
b824c9
	if (logfile) {
b824c9
		if ((fdlog[1] = __sys_openat(
b824c9
				ntux_driver_fdcwd(dctx),
b824c9
				logfile,O_CREAT|O_TRUNC|O_WRONLY,0)) < 0)
b824c9
			if (ntux_errno_set(dctx,fdlog[1]))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
	} else {
b824c9
		if ((ret = __sys_pipe(fdlog)) < 0)
b824c9
			if (ntux_errno_set(dctx,ret))
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
	}
b824c9
b824c9
	/* spawn */
b824c9
	pid = __sys_vfork();
b824c9
b824c9
	/* failed? */
b824c9
	if (pid < 0)
b824c9
		if (ntux_errno_set(dctx,pid))
b824c9
			return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
	/* child */
b824c9
	if (pid == 0)
b824c9
		if ((status = __sys_execve(program,argv,envp)))
b824c9
			if (ntux_errno_set(dctx,status))
b824c9
				if (NTUX_SYSTEM_ERROR(dctx))
b824c9
					__sys_exit(0);
b824c9
b824c9
	/* parent */
b824c9
	__sys_close(fdlog[1]);
b824c9
b824c9
	if (dctx->cctx->logfile) {
b824c9
		__sys_wait4(
b824c9
			pid,&status,
b824c9
			0,0);
b824c9
b824c9
		return 0;
b824c9
	}
b824c9
b824c9
	/* piped bridge output */
b824c9
	rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
b824c9
b824c9
	while (rbytes == -EINTR)
b824c9
		rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
b824c9
b824c9
	while (rbytes > 0) {
b824c9
		for (ch=buf; rbytes; ch += wbytes) {
b824c9
			wbytes = __sys_write(2,ch,rbytes);
b824c9
b824c9
			while (wbytes == -EINTR)
b824c9
				wbytes = __sys_write(2,buf,rbytes);
b824c9
b824c9
			if (wbytes < 0) {
b824c9
				__sys_close(fdlog[0]);
b824c9
				ntux_errno_set(dctx,wbytes);
b824c9
				return NTUX_SYSTEM_ERROR(dctx);
b824c9
			}
b824c9
b824c9
			rbytes -= wbytes;
b824c9
		}
b824c9
b824c9
		rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
b824c9
b824c9
		while (rbytes == -EINTR)
b824c9
			rbytes = __sys_read(fdlog[0],buf,sizeof(buf));
b824c9
	}
b824c9
b824c9
	__sys_close(fdlog[0]);
b824c9
b824c9
	if (rbytes < 0)
b824c9
		if (ntux_errno_set(dctx,rbytes))
b824c9
			return NTUX_SYSTEM_ERROR(dctx);
b824c9
b824c9
	/* wait */
b824c9
	struct ntux_driver_ctx_impl * ictx = ntux_get_driver_ictx(dctx);
b824c9
b824c9
	__sys_wait4(
b824c9
		pid,
b824c9
		&ictx->cctx.status,
b824c9
		0,0);
b824c9
b824c9
	return 0;
b824c9
}