Blob Blame History Raw
/*********************************************************/
/*  ptycon: a pty-console bridge                         */
/*  Copyright (C) 2016--2017  SysDeer Technologies, LLC  */
/*  Released under GPLv2 and GPLv3; see COPYING.PTYCON.  */
/*********************************************************/

#include <psxtypes/psxtypes.h>
#include <pemagine/pemagine.h>
#include <ntapi/nt_status.h>
#include <ntapi/nt_object.h>
#include <ntapi/nt_thread.h>
#include <ntapi/nt_process.h>
#include <ntapi/nt_string.h>
#include <ntapi/ntapi.h>

#include <ptycon/ptycon.h>
#include "ptycon_driver_impl.h"

int ptyc_spawn(struct ptyc_driver_ctx * dctx)
{
	int32_t				status;
	nt_spawn_process_params		sparams;
	nt_runtime_data			rtctx;
	struct ptyc_driver_ctx_impl *	ictx;
	struct ptyc_client_ctx *	clctx;
	nt_rtdata *			self;

	/* init */
	if (!(ictx = ptyc_get_driver_ictx(dctx)))
		return NT_STATUS_INVALID_HANDLE;

	if (!dctx->cctx->eargv)
		return NT_STATUS_SUCCESS;

	self  = ictx->rtdata;
	clctx = &ictx->clctx;

	/* sparams */
	ntapi->tt_aligned_block_memset(
		&sparams,0,sizeof(sparams));

	sparams.rtctx    = &rtctx;
	sparams.patharg  = dctx->cctx->eargv[0];
	sparams.argv     = dctx->cctx->eargv;
	sparams.envp     = self->envp;
	sparams.hsession = self->hsession;
	sparams.hroot    = dctx->cctx->hroot
				? dctx->cctx->hroot
				: self->hroot;

	/* rtctx */
	ntapi->tt_aligned_block_memset(
		&rtctx,0,sizeof(rtctx));

	ntapi->tt_aligned_block_memcpy(
		(uintptr_t *)&rtctx.cid_parent,
		(uintptr_t *)&self->cid_self,
		sizeof(nt_cid));

	rtctx.hcwd  = self->hcwd;
	rtctx.hroot = sparams.hroot;

	rtctx.tty_type    = self->tty_type;
	rtctx.tty_subtype = self->tty_subtype;

	rtctx.tty_keys[0] = self->tty_keys[0];
	rtctx.tty_keys[1] = self->tty_keys[1];
	rtctx.tty_keys[2] = self->tty_keys[2];
	rtctx.tty_keys[3] = self->tty_keys[3];
	rtctx.tty_keys[4] = self->tty_keys[4];
	rtctx.tty_keys[5] = self->tty_keys[5];

	ntapi->tt_guid_copy(
		&rtctx.tty_guid,
		&self->tty_guid);

	rtctx.hstdin      = NT_INVALID_HANDLE_VALUE;
	rtctx.hstdout     = NT_INVALID_HANDLE_VALUE;
	rtctx.hstderr     = NT_INVALID_HANDLE_VALUE;

	rtctx.stdin_type  = NT_FILE_TYPE_PTY;
	rtctx.stdout_type = NT_FILE_TYPE_PTY;
	rtctx.stderr_type = NT_FILE_TYPE_PTY;

	rtctx.ptyin [0]   = clctx->clinfo.any[0];
	rtctx.ptyin [1]   = clctx->clinfo.any[1];
	rtctx.ptyin [2]   = clctx->clinfo.any[2];
	rtctx.ptyin [3]   = clctx->clinfo.any[3];

	rtctx.ptyout[0]   = clctx->clinfo.any[0];
	rtctx.ptyout[1]   = clctx->clinfo.any[1];
	rtctx.ptyout[2]   = clctx->clinfo.any[2];
	rtctx.ptyout[3]   = clctx->clinfo.any[3];

	rtctx.ptyerr[0]   = clctx->clinfo.any[0];
	rtctx.ptyerr[1]   = clctx->clinfo.any[1];
	rtctx.ptyerr[2]   = clctx->clinfo.any[2];
	rtctx.ptyerr[3]   = clctx->clinfo.any[3];

	rtctx.ptyctl[0]   = clctx->clinfo.any[0];
	rtctx.ptyctl[1]   = clctx->clinfo.any[1];
	rtctx.ptyctl[2]   = clctx->clinfo.any[2];
	rtctx.ptyctl[3]   = clctx->clinfo.any[3];

	/* hoppla */
	if ((status = ntapi->tt_spawn_native_process(&sparams)))
		return status;

	/* clctx */
	clctx->hprocess		= sparams.hprocess;
	clctx->hthread		= sparams.hthread;
	clctx->cid.process_id	= sparams.cid.process_id;
	clctx->cid.thread_id	= sparams.cid.thread_id;

	/* child ready? */
	if (!(sparams.eready.signal_state))
		return NT_STATUS_GENERIC_COMMAND_FAILED;

	/* finalize */
	if (dctx->cctx->drvflags & (PTYC_DRIVER_DBG_RAW|PTYC_DRIVER_DBG_OVEN))
		return NT_STATUS_SUCCESS;

	if ((status = ntapi->pty_close(ictx->cctx.hpts)))
		return status;

	ictx->cctx.hpts = 0;

	/* all done */
	return NT_STATUS_SUCCESS;
}