/*********************************************************/ /* ptycon: a pty-console bridge */ /* Copyright (C) 2016--2017 SysDeer Technologies, LLC */ /* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ /*********************************************************/ #include #include #include #include #include "ptycon_driver_impl.h" #include "ptycon_ioctl_impl.h" #include "ptycon_status_impl.h" static int32_t ptyc_pty_open(nt_pty * hptm, nt_guid * pty_guid, nt_pty ** hpty) { nt_vfd_dev_name pty_name; nt_oa oa = {sizeof(oa),0,0,0,0,0}; ntapi->vfd_dev_name_init( &pty_name,pty_guid); oa.obj_name = &pty_name.name; oa.root_dir = hptm; return ntapi->pty_open( 0,hpty, NT_FILE_ALL_ACCESS, &oa,0,0,0); } static int32_t ptyc_ptm_open(struct ptyc_common_ctx * cctx) { nt_guid pty_guid = TTY_PTM_GUID; return ptyc_pty_open( 0,&pty_guid, &cctx->hptm); } static int32_t ptyc_pts_open(struct ptyc_common_ctx * cctx) { int32_t status; nt_guid pty_guid = TTY_PTS_GUID; if ((status = ptyc_grant(cctx->hptm))) return status; return ptyc_pty_open( cctx->hptm,&pty_guid, &cctx->hpts); } static int32_t ptyc_make_raw(nt_pty * hpty) { int32_t status; nt_iosb iosb; nt_tty_sigctl_info ctlinfo; struct tty_termios termios; ntapi->tt_aligned_block_memset( &ctlinfo,0,sizeof(ctlinfo)); if ((status = ntapi->pty_ioctl( hpty, 0,0,0, &iosb, TTY_TCGETS, &ctlinfo,sizeof(ctlinfo), &ctlinfo,sizeof(ctlinfo)))) return status; ntapi->tt_generic_memcpy( &termios, &ctlinfo.terminfo, sizeof(termios)); termios.c_oflag &= ~TTY_OPOST; termios.c_cflag &= ~(TTY_CSIZE | TTY_PARENB); termios.c_cflag |= TTY_CS8; termios.c_lflag &= ~(TTY_ECHO | TTY_ECHONL | TTY_ICANON | TTY_ISIG | TTY_IEXTEN); termios.c_iflag &= ~(TTY_IGNBRK | TTY_BRKINT | TTY_PARMRK | TTY_ISTRIP | TTY_INLCR | TTY_IGNCR | TTY_ICRNL | TTY_IXON); ntapi->tt_aligned_block_memset( &ctlinfo,0,sizeof(ctlinfo)); ntapi->tt_generic_memcpy( &ctlinfo.terminfo, &termios, sizeof(termios)); return ntapi->pty_ioctl( hpty, 0,0,0, &iosb, TTY_TCSETS, &ctlinfo,sizeof(ctlinfo), &ctlinfo,sizeof(ctlinfo)); } static int32_t ptyc_make_oven(nt_pty * hpty) { int32_t status; nt_iosb iosb; nt_tty_sigctl_info ctlinfo; struct tty_termios termios; ntapi->tt_aligned_block_memset( &ctlinfo,0,sizeof(ctlinfo)); if ((status = ntapi->pty_ioctl( hpty, 0,0,0, &iosb, TTY_TCGETS, &ctlinfo,sizeof(ctlinfo), &ctlinfo,sizeof(ctlinfo)))) return status; ntapi->tt_generic_memcpy( &termios, &ctlinfo.terminfo, sizeof(termios)); termios.c_cflag = TTY_CBAUD | TTY_CREAD | TTY_CS8 | TTY_HUPCL; termios.c_iflag = TTY_ICRNL | TTY_BRKINT | TTY_IXON; termios.c_lflag = TTY_ECHO | TTY_ECHOCTL | TTY_ECHOE | TTY_ECHOK | TTY_ECHOKE | TTY_ICANON | TTY_ISIG | TTY_IEXTEN; termios.c_oflag = TTY_OPOST | TTY_ONLCR | TTY_TAB0 | TTY_VT0 | TTY_BS0 | TTY_CR0 | TTY_FF0 | TTY_NL0; ntapi->tt_aligned_block_memset( &ctlinfo,0,sizeof(ctlinfo)); ntapi->tt_generic_memcpy( &ctlinfo.terminfo, &termios, sizeof(termios)); return ntapi->pty_ioctl( hpty, 0,0,0, &iosb, TTY_TCSETS, &ctlinfo,sizeof(ctlinfo), &ctlinfo,sizeof(ctlinfo)); } int ptyc_alloc_pty(struct ptyc_driver_ctx * dctx) { int32_t status; struct ptyc_driver_ctx_impl * ictx; struct ptyc_common_ctx * cctx; if (!(ictx = ptyc_get_driver_ictx(dctx))) return NT_STATUS_INVALID_HANDLE; cctx = &ictx->cctx; if (cctx->hpts || cctx->hptm) return ptyc_set_status( dctx,NT_STATUS_DEVICE_ALREADY_ATTACHED); if ((status = ptyc_ptm_open(cctx))) return ptyc_set_status( dctx,status); if ((status = ptyc_make_raw(cctx->hptm))) return ptyc_set_status( dctx,status); if ((status = ptyc_pts_open(cctx))) return ptyc_set_status( dctx,status); if ((status = ptyc_set_client_info(cctx->hpts,&ictx->clctx.clinfo))) return ptyc_set_status( dctx,status); if (cctx->drvflags & PTYC_DRIVER_DBG_RAW) if ((status = ptyc_make_raw(cctx->hpts))) return ptyc_set_status( dctx,status); if (cctx->drvflags & PTYC_DRIVER_DBG_OVEN) if ((status = ptyc_make_oven(cctx->hpts))) return ptyc_set_status( dctx,status); if (cctx->drvflags & (PTYC_DRIVER_DBG_RAW|PTYC_DRIVER_DBG_OVEN)) if ((status = ptyc_pty_own(cctx->hpts,ictx->rtdata))) return ptyc_set_status( dctx,status); return ptyc_set_status( dctx,NT_STATUS_SUCCESS); } void ptyc_free_pty(struct ptyc_driver_ctx * dctx) { struct ptyc_driver_ctx_impl * ictx; if (!(ictx = ptyc_get_driver_ictx(dctx))) return; if (ictx->cctx.hpts) { ntapi->pty_close(ictx->cctx.hpts); ictx->cctx.hpts = 0; } if (ictx->cctx.hptm) { ntapi->pty_close(ictx->cctx.hptm); ictx->cctx.hptm = 0; } }