summaryrefslogtreecommitdiffhomepage
path: root/src/pty/ptyc_spawn.c
blob: 5a7e7ab10d2acc33a8458dea2a86294c9b242118 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*********************************************************/
/*  ptycon: a pty-console bridge                         */
/*  Copyright (C) 2016--2017  Z. Gilboa                  */
/*  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)))
		if ((status = ntapi->pty_close(ictx->cctx.hpts)))
			return status;

	/* all done */
	return NT_STATUS_SUCCESS;
}