/*********************************************************/
/* ptycon: a pty-console bridge */
/* Copyright (C) 2016--2017 Z. Gilboa */
/* Released under GPLv2 and GPLv3; see COPYING.PTYCON. */
/*********************************************************/
#include <ntapi/ntapi.h>
#include <stdio.h>
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;
}