/*********************************************************/ /* ptycon: a pty-console bridge */ /* Copyright (C) 2016--2017 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */ /*********************************************************/ #include #include extern const ntapi_vtbl * ptyc_ntapi; typedef struct ptyc_file { void * hany; } FILE; int ptyc_fputs(const char * str, FILE * file) { int32_t status; nt_runtime_data * rtdata; ntapi_zw_write_file * iofn; void * hio; void * hevent; int fdtype; size_t size; size_t nbytes; nt_iosb iosb; /* rtdata */ if (ptyc_ntapi->tt_get_runtime_data(&rtdata,0)) return -1; /* io type */ if (file == (void *)0) { hio = rtdata->hstdin; fdtype = rtdata->stdin_type; } else if (file == (void *)1) { hio = rtdata->hstdout; fdtype = rtdata->stdout_type; } else if (file == (void *)2) { hio = rtdata->hstderr; fdtype = rtdata->stderr_type; } else { return -1; } if (!hio) return -1; /* buffer */ size = ptyc_ntapi->tt_string_null_offset_multibyte(str); nbytes = size; /* iofn */ iofn = (fdtype == NT_FILE_TYPE_PTY) ? (ntapi_zw_write_file *)ptyc_ntapi->pty_write : ptyc_ntapi->zw_write_file; /* hevent */ if ((status = ptyc_ntapi->tt_create_private_event( &hevent, NT_NOTIFICATION_EVENT, NT_EVENT_NOT_SIGNALED))) return -1; while (nbytes) { /* iowrite */ status = iofn( hio,hevent, 0,0,&iosb, (void *)str, (uint32_t)nbytes,0,0); /* wait */ if (status == NT_STATUS_PENDING) status = ptyc_ntapi->zw_wait_for_single_object( hevent,0,0); /* check */ if (status || iosb.status) { ptyc_ntapi->zw_close(hevent); return -1; } str += iosb.info; nbytes -= iosb.info; } /* all done */ ptyc_ntapi->zw_close( hevent); return (int)size; } int ptyc_fprintf(FILE * file, const char * fmt, ...) { va_list ap; char * str; size_t buffer[32768/sizeof(size_t)]; ptyc_ntapi->tt_aligned_block_memset( buffer,0,sizeof(buffer)); str = (char *)buffer; va_start(ap, fmt); ptyc_ntapi->vsnprintf(str, sizeof(buffer), fmt, ap); va_end(ap); str[sizeof(buffer)-1] = 0; return ptyc_fputs(str,file); } int ptyc_sprintf(char * str, const char * fmt, ...) { int ret; va_list ap; va_start(ap, fmt); ret = ptyc_ntapi->vsprintf(str, fmt, ap); va_end(ap); return ret; } int ptyc_snprintf(char * str, size_t n, const char * fmt, ...) { int ret; va_list ap; va_start(ap, fmt); ret = ptyc_ntapi->vsnprintf(str, n, fmt, ap); va_end(ap); return ret; } int ptyc_isatty(int fildes) { nt_runtime_data * rtdata; if ((ptyc_ntapi->tt_get_runtime_data(&rtdata,0))) return 0; if (fildes == 0) return (rtdata->stdin_type == NT_FILE_TYPE_PTY); else if (fildes == 1) return (rtdata->stdout_type == NT_FILE_TYPE_PTY); else if (fildes == 2) return (rtdata->stderr_type == NT_FILE_TYPE_PTY); else return 0; } int ptyc_fileno(void * any) { return (int)(intptr_t)any; } int ptyc_write(int fd, const void * buf, size_t size) { int32_t status; nt_runtime_data * rtdata; ntapi_zw_write_file * iofn; void * hio; void * hevent; int fdtype; nt_iosb iosb; /* size */ if (size >= 0x80000000) return NT_STATUS_INVALID_PARAMETER; /* rtdata */ if (ptyc_ntapi->tt_get_runtime_data(&rtdata,0)) return NT_STATUS_REINITIALIZATION_NEEDED; /* hio, io type */ if (fd == STDIN_FILENO) { hio = rtdata->hstdin; fdtype = rtdata->stdin_type; } else if (fd == STDOUT_FILENO) { hio = rtdata->hstdout; fdtype = rtdata->stdout_type; } else if (fd == STDERR_FILENO) { hio = rtdata->hstderr; fdtype = rtdata->stderr_type; } else { return NT_STATUS_INVALID_PARAMETER; } if (!hio) return NT_STATUS_INVALID_HANDLE; /* iofn */ iofn = (fdtype == NT_FILE_TYPE_PTY) ? (ntapi_zw_write_file *)ptyc_ntapi->pty_write : ptyc_ntapi->zw_write_file; /* hevent */ if ((status = ptyc_ntapi->tt_create_private_event( &hevent, NT_NOTIFICATION_EVENT, NT_EVENT_NOT_SIGNALED))) return status; /* iowrite */ status = iofn( hio,hevent, 0,0,&iosb, (void *)buf,size, 0,0); /* wait */ if (status == NT_STATUS_PENDING) status = ptyc_ntapi->zw_wait_for_single_object( hevent,0,0); /* hevent */ ptyc_ntapi->zw_close(hevent); /* ret */ return status ? status : iosb.status; }