/*********************************************************/ /* ptycon: a pty-console bridge */ /* Copyright (C) 2016--2017 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ /*********************************************************/ #include #include #include #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; }