/*********************************************************/
/* ptycon: a pty-console bridge */
/* Copyright (C) 2016--2017 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */
/*********************************************************/
#include <pemagine/pemagine.h>
#include <ntapi/ntapi.h>
#include <ptycon/ptycon.h>
#include "ptycon_init_impl.h"
#include "ptycon_driver_impl.h"
static const nt_guid ptycon_daemon_guid = PTYC_PORT_GUID_DAEMON;
static void ptycon_exit(int code)
{
/* posix exit code? */
if (code <= 0xff)
code <<= 8;
ntapi->zw_terminate_process(
NT_CURRENT_PROCESS_HANDLE,
code);
}
static int ptycon_dbg_helper(int32_t status)
{
return status ? -1 : 0;
}
static int ptycon_dbg_init(char ** argv)
{
if (argv[1] && !(ntapi->tt_strcmp_multibyte(argv[1],"--wait")))
return ptycon_dbg_helper(
ntapi->tt_wait_for_dummy_event());
return 0;
}
static int32_t ptycon_start(char ** argv, char ** envp)
{
int32_t status;
nt_runtime_data * rtdata;
nt_port_attr port_attr;
nt_pty_client_info client_info;
nt_iosb iosb;
/* rtdata */
if ((status = ntapi->tt_get_runtime_data(&rtdata,0)))
return status;
if (rtdata->argv) {
argv = rtdata->argv;
envp = rtdata->envp;
}
/* early debug (optional) */
ptycon_dbg_init(argv);
/* daemon */
if (!(ntapi->tt_guid_compare(
&rtdata->srv_guid,
&(nt_guid)NT_PORT_GUID_DEFAULT)))
ntapi->tt_guid_copy(
&rtdata->srv_guid,
&ptycon_daemon_guid);
/* no tty session? */
if (!rtdata->tty_keys[0])
return ptyc_main(argv,envp);
/* tty */
ntapi->tt_aligned_block_memset(
&port_attr,0,sizeof(port_attr));
port_attr.type = NT_PORT_TYPE_SUBSYSTEM;
port_attr.subtype = NT_PORT_SUBTYPE_DEFAULT;
port_attr.keys.key[0] = rtdata->tty_keys[0];
port_attr.keys.key[1] = rtdata->tty_keys[1];
port_attr.keys.key[2] = rtdata->tty_keys[2];
port_attr.keys.key[3] = rtdata->tty_keys[3];
port_attr.keys.key[4] = rtdata->tty_keys[4];
port_attr.keys.key[5] = rtdata->tty_keys[5];
ntapi->tt_guid_copy(
&port_attr.guid,
&rtdata->tty_guid);
if ((status = ntapi->tty_join_session(
&rtdata->hsession,0,
&port_attr,
NT_TTY_SESSION_PRIMARY)))
return status;
/* pty */
if ((status = ntapi->pty_inherit_runtime_ctty(
rtdata->hsession,
rtdata)))
return status;
/* ctty identification */
if (rtdata->hctty) {
client_info.any[0] = 0;
client_info.any[1] = 0;
client_info.any[2] = 0;
client_info.any[3] = 0;
if ((status = ntapi->pty_set(
rtdata->hctty,&iosb,
&client_info,sizeof(client_info),
NT_PTY_CLIENT_INFORMATION)))
return status;
}
/* ready */
if (rtdata->hready)
if ((status = ntapi->zw_set_event(rtdata->hready,0)))
return status;
/* main */
return ptyc_main(argv,envp);
}
static int __stdcall ptycon_daemon_entry_point(void * hswap)
{
int32_t status;
int argc;
char ** argv;
char ** envp;
ntapi->zw_set_event(hswap,0);
ntapi->zw_close(hswap);
if ((status = ntapi->tt_get_argv_envp_utf8(
&argc,&argv,&envp,
0,0,0)))
ptycon_exit(status);
ptycon_exit(ptycon_start(argv,envp));
return NT_STATUS_INTERNAL_ERROR;
}
int ptycon_entry_point(void)
{
int32_t status;
nt_thread_params params;
void * hswap;
if ((status = ptyc_init()))
return status;
if ((status = ntapi->tt_create_private_event(
&hswap,
NT_NOTIFICATION_EVENT,
NT_EVENT_NOT_SIGNALED)))
return status;
ntapi->tt_aligned_block_memset(
¶ms,0,sizeof(params));
params.hprocess = NT_CURRENT_PROCESS_HANDLE;
params.start = ptycon_daemon_entry_point;
params.arg = hswap;
params.stack_size_commit = 128 * 1024;
params.stack_size_reserve = 128 * 1024;
params.creation_flags = NT_CREATE_LOCAL_THREAD;
if ((status = ntapi->tt_create_thread(¶ms)))
ptycon_exit(status);
ntapi->zw_wait_for_single_object(
hswap,NT_SYNC_NON_ALERTABLE,0);
ntapi->zw_close(
params.hthread);
ntapi->zw_terminate_thread(
NT_CURRENT_THREAD_HANDLE,
NT_STATUS_SUCCESS);
return NT_STATUS_INTERNAL_ERROR;
}