Initial code for the VT-100 terminal emulator that runs in the W32

subsystem and connects to the PSXSS.EXE (WIP).

svn path=/trunk/; revision=2732
This commit is contained in:
Emanuele Aliberti 2002-03-17 22:15:39 +00:00
parent 8571b1561a
commit ab561cad5a
9 changed files with 3552 additions and 0 deletions

View file

@ -0,0 +1,90 @@
08/08/96 - John L. Miller, johnmil@cs.cmu.edu, johnmil@jprc.com
FILES INCLUDED:
00readme.txt - this file
VT100.H - Definitions for VT-100 emulator.
VT100.C - Front end parsing code for VT-100 emulator
CONSOLE.C - Back-end code to allow VT-100 in WinNt/Win95 console
Many UNIX users take terminals for granted, as something you get for free
with the operating system. Unfortunately, this isn't the case for many
non-unix operating systems, especially PC-based ones. After a number of
projects, I decided it would be nice if there was source publicly available
for doing VT-100 emulation.
The files included with this distribution are not a complete implementation
of VT-100 terminal emulation, but do provide complete enough coverage to
use many vt-100 functions over the network. For instance, its enough to
use EMACS to edit, or to connect up to your favorite mud with ANSI color
and graphics characters.
The VT-100 emulator is broken into two parts. The first is the front end,
vt100.c and vt100.h. These files were written to be fairly device-independant,
though admittedly if you're running under a 16-bit operating system instead
of a 32-bit, you might need to change some of the 'int' values to 'long.'
Otherwise, it should work 'as-is'.
The second part is a back-end. The back-end is responsible for doing the
workhorse activities. The front-end parses a character stream, and decides
whether to clear a part of the screen, or move the cursor, or switch fonts.
Then it calls routines in the back-end to perform these activities.
The back-end functions are, for the most part, very straight forward, and
quite easy to implement compared to writing a vt-100 emulator from scratch.
CONSOLE.C is a back-end for use in console (command, dos) windows under
Windows 95 and Windows NT. This console vt-100 emulator is also being used
in my TINTIN-III port and kerberized encrypted telnet port.
TO USE THIS VT-100 EMULATOR:
First, it's intended to be linked directly into source code. You'll need
to change printf's and puts' in your source code to call vtprintf() and
vtputs() instead. You can add additional functions to vt100.c as you see
fit to handle other output functions like putchar() and write(). Another
routine you may want to use is vtProcessedTextOut(), which accepts a
buffer to output, and a count of characters in that buffer.
Second, you need to make sure that your source code calls vtInitVT100()
before it does ANYTHING else. This initializes the vt-100 emulator.
Third, if you want to use this VT-100 emulator with anything besides
Windows NT and Windows 95 consoles, you'll need to implement your own
back end. The list of functions you will need to supply, as well as what
they need to do is contained in vt100.h. The list (minus descriptions)
is as follows:
int beInitVT100Terminal();
int beAbsoluteCursor(int row, int col);
int beOffsetCursor(int row, int column);
int beRestoreCursor(void);
int beSaveCursor(void);
int beSetTextAttributes(int fore, int back);
int beRawTextOut(char *text, int len);
int beEraseText(int rowFrom, int colFrom, int rowTo, int colTo);
int beDeleteText(int rowFrom, int colFrom, int rowTo, int colTo);
int beInsertRow(int row);
int beTransmitText(char *text, int len);
int beAdvanceToTab(void);
int beClearTab(int col);
int beSetScrollingRows(int fromRow, int toRow);
int beRingBell(void);
int beGetTermMode();
int beSetTermMode(int newMode);
For details on what each of these does, read the descriptions of each
function included in vt100.h, and read over CONSOLE.C for examples. I've
included copious comments in all of these files to try to make them as
easy to use as possible.
In any case, it should be easier than writing a VT-100 emulator from
scratch.
KNOWN BUGS -
o Many features of VT-100 emulation aren't implemented. This includes
support for graphics character set 0 and many of the
answerback functions.
Well, good luck!

View file

@ -0,0 +1,23 @@
# $Id: Makefile,v 1.1 2002/03/17 22:15:39 ea Exp $
#
# POSIX+ Terminal Emulator that runs in the W32 subsystem.
#
PATH_TO_TOP=../../../..
PATH_TO_TOP_PSX=../..
TARGET_NAME=csrterm
TARGET_TYPE=program
TARGET_APPTYPE=console
TARGET_CFLAGS =-I$(PATH_TO_TOP_PSX)/include
TARGET_SDKLIBS=ntdll.a kernel32.a
TARGET_OBJECTS=\
$(TARGET_NAME).o \
console.o \
vt100.o \
$(TARGET_NAME).coff
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
# EOF

1243
posix/apps/csrterm/console.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,582 @@
/* $Id: csrterm.c,v 1.1 2002/03/17 22:15:39 ea Exp $
*
* PROJECT : ReactOS Operating System / POSIX+ Environment Subsystem
* DESCRIPTION: CSRTERM - A DEC VT-100 terminal emulator for the PSX subsystem
* DESCRIPTION: that runs in the Win32 subsystem.
* COPYRIGHT : Copyright (c) 2001-2002 Emanuele Aliberti
* LICENSE : GNU GPL v2
* DATE : 2001-05-05
* AUTHOR : Emanuele Aliberti <ea@iol.it>
* NOTE : This IS a Win32 program, but will fail if the PSX subsystem
* NOTE : is not installed. The PSX subsystem consists of two more
* NOTE : files: PSXSS.EXE, PSXDLL.DLL.
* WARNING : If you use this program under a real NT descendant, be
* WARNING : sure to have disabled the PSX subsystem.
* --------------------------------------------------------------------
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write
* to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
* MA 02139, USA.
*
* --------------------------------------------------------------------
* 2002-03-16 EA Today it actually compiled.
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define NTOS_MODE_USER
#include <ntos.h>
#include <psx/lpcproto.h>
#include "vt100.h"
#include "csrterm.h"
/*** OPTIONS *********************************************************/
#define PRIVATE static
#define INPUT_QUEUE_SIZE 32
#ifdef NDEBUG
#define TRACE
#else
#define TRACE OutputDebugString(__FUNCTION__)
#endif
/*** GLOBALS *********************************************************/
PRIVATE LPCSTR MyName = "CSRTERM";
PRIVATE CSRTERM_SESSION Session;
/*** PRIVATE FUNCTIONS ***********************************************/
VOID STDCALL Debug_Print (LPCSTR Format, ...)
{
CHAR Buffer [512];
va_list ArgumentPointer;
va_start(ArgumentPointer, Format);
vsprintf(Buffer, Format, ArgumentPointer);
va_end(ArgumentPointer);
OutputDebugStringA (Buffer);
}
/**********************************************************************
* OutPort/2 PRIVATE
*
* DESCRIPTION
* Notify to PSXSS that input data is ready by sending a
* software interrupt on the \POSIX+\SessionPort port.
*/
PRIVATE DWORD STDCALL OutPort (PCHAR Buffer, ULONG Size)
{
NTSTATUS Status;
PSX_TERMINAL_READ TerminalRead;
TRACE;
if (Size > 0)
{
/* LPC */
TerminalRead.Header.MessageType = LPC_NEW_MESSAGE;
TerminalRead.PsxHeader.Context = PSX_CONNECTION_TYPE_TERMINAL;
TerminalRead.PsxHeader.Procedure = PSX_TERMINAL_INTERRUPT;
/* Terminal I/O */
TerminalRead.Size = Size;
RtlCopyMemory (TerminalRead.Buffer, Buffer, Size);
#if 0
Status = NtRequestWaitReplyPort (
Session.ServerPort.Handle,
& TerminalRead
/* FIXME */
);
#endif
if (!NT_SUCCESS(Status))
{
vtprintf ("%s: %s: NtRequestWaitReplyPort failed with %08x\n",
MyName, __FUNCTION__, Status);
return 0;
}
}
return Size;
}
/**********************************************************************
* ProcessConnectionRequest/1 PRIVATE
*
* DESCRIPTION
* Initialize our data for managing the control connection
* initiated by the PSXSS.EXE process.
*/
PRIVATE NTSTATUS STDCALL ProcessConnectionRequest (PPSX_MAX_MESSAGE Request)
{
TRACE;
Session.SsLinkIsActive = TRUE;
return STATUS_SUCCESS;
}
/**********************************************************************
* ProcessRequest/1 PRIVATE
*
* DESCRIPTION
*
*/
PRIVATE NTSTATUS STDCALL ProcessRequest (PPSX_MAX_MESSAGE Request)
{
TRACE;
/* TODO */
vtprintf("TEST VT-100\n");
return STATUS_SUCCESS;
}
/**********************************************************************
* PsxSessionPortListener/1 PRIVATE
*
* DESCRIPTION
* Manage messages from the PSXSS, that is LPC messages we get
* from the PSXSS process to our \POSIX+\Sessions\P<pid> port.
*
* NOTE
* This function is the thread 's entry point created in
* CreateSessionObiects().
*/
PRIVATE DWORD STDCALL PsxSessionPortListener (LPVOID Arg)
{
NTSTATUS Status;
LPC_TYPE RequestType;
PSX_MAX_MESSAGE Request;
PPSX_MAX_MESSAGE Reply = NULL;
BOOL NullReply = FALSE;
TRACE;
while (TRUE)
{
Reply = NULL;
while (!NullReply)
{
Status = NtReplyWaitReceivePort (
Session.Port.Handle,
0,
(PLPC_MESSAGE) Reply,
(PLPC_MESSAGE) & Request
);
if (!NT_SUCCESS(Status))
{
break;
}
RequestType = PORT_MESSAGE_TYPE(Request);
switch (RequestType)
{
case LPC_CONNECTION_REQUEST:
ProcessConnectionRequest (& Request);
NullReply = TRUE;
continue;
case LPC_CLIENT_DIED:
case LPC_PORT_CLOSED:
case LPC_DEBUG_EVENT:
case LPC_ERROR_EVENT:
case LPC_EXCEPTION:
NullReply = TRUE;
continue;
default:
if (RequestType != LPC_REQUEST)
{
NullReply = TRUE;
continue;
}
}
Reply = & Request;
Reply->PsxHeader.Status = ProcessRequest (& Request);
NullReply = FALSE;
}
if ((STATUS_INVALID_HANDLE == Status) ||
(STATUS_OBJECT_TYPE_MISMATCH == Status))
{
break;
}
}
Session.SsLinkIsActive = FALSE;
TerminateThread (GetCurrentThread(), Status);
}
/**********************************************************************
* CreateSessionObiects/1 PRIVATE
*
* DESCRIPTION
* Create the session objects which are mananged by our side:
*
* \POSIX+\Sessions\P<pid>
* \POSIX+\Sessions\D<pid>
*/
PRIVATE NTSTATUS STDCALL CreateSessionObjects (DWORD Pid)
{
NTSTATUS Status;
ULONG Id = 0;
OBJECT_ATTRIBUTES Oa;
TRACE;
/* Critical section */
Status = RtlInitializeCriticalSection (& Session.Lock);
if (!NT_SUCCESS(Status))
{
vtprintf (
"%s: %s: RtlInitializeCriticalSection failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
/* Port and port management thread */
swprintf (
Session.Port.NameBuffer,
PSX_NS_SESSION_PORT_TEMPLATE,
PSX_NS_SUBSYSTEM_DIRECTORY_NAME,
PSX_NS_SESSION_DIRECTORY_NAME,
Pid
);
RtlInitUnicodeString (& Session.Port.Name, Session.Port.NameBuffer);
InitializeObjectAttributes (& Oa, & Session.Port.Name, 0, NULL, NULL);
Status = NtCreatePort (& Session.Port.Handle, & Oa, 0, 0, 0x10000);
if (!NT_SUCCESS(Status))
{
RtlDeleteCriticalSection (& Session.Lock);
vtprintf ("%s: %s: NtCreatePort failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
Session.Port.Thread.Handle =
CreateThread (
NULL,
0,
PsxSessionPortListener,
0,
CREATE_SUSPENDED,
& Session.Port.Thread.Id
);
if ((HANDLE) NULL == Session.Port.Thread.Handle)
{
Status = (NTSTATUS) GetLastError();
NtClose (Session.Port.Handle);
RtlDeleteCriticalSection (& Session.Lock);
vtprintf ("%s: %s: CreateThread failed with %d\n",
MyName, __FUNCTION__, Status);
return Status;
}
/* Section */
swprintf (
Session.Section.NameBuffer,
PSX_NS_SESSION_DATA_TEMPLATE,
PSX_NS_SUBSYSTEM_DIRECTORY_NAME,
PSX_NS_SESSION_DIRECTORY_NAME,
Pid
);
RtlInitUnicodeString (& Session.Section.Name, Session.Section.NameBuffer);
InitializeObjectAttributes (& Oa, & Session.Section.Name, 0, 0, 0);
Status = NtCreateSection (
& Session.Section.Handle,
0, /* DesiredAccess */
& Oa,
NULL, /* SectionSize OPTIONAL */
PAGE_READWRITE, /* Protect 4 */
SEC_COMMIT, /* Attributes */
0 /* FileHandle: 0=pagefile.sys */
);
if (!NT_SUCCESS(Status))
{
NtClose (Session.Port.Handle);
NtTerminateThread (Session.Port.Thread.Handle, Status);
RtlDeleteCriticalSection (& Session.Lock);
vtprintf ("%s: %s: NtCreateSection failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
Session.Section.BaseAddress = NULL;
Session.Section.ViewSize = 0;
Status = NtMapViewOfSection (
Session.Section.Handle,
NtCurrentProcess(),
& Session.Section.BaseAddress,
0, /* ZeroBits */
0, /* Commitsize */
0, /* SectionOffset */
& Session.Section.ViewSize,
ViewUnmap,
0, /* AllocationType */
PAGE_READWRITE /* Protect 4 */
);
if (!NT_SUCCESS(Status))
{
NtClose (Session.Port.Handle);
NtTerminateThread (Session.Port.Thread.Handle, Status);
NtClose (Session.Section.Handle);
RtlDeleteCriticalSection (& Session.Lock);
vtprintf ("%s: %s: NtMapViewOfSection failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
return Status;
}
/**********************************************************************
* CreateTerminalToPsxChannel/0 PRIVATE
*
* DESCRIPTION
*
*/
PRIVATE NTSTATUS STDCALL CreateTerminalToPsxChannel (VOID)
{
PSX_CONNECT_PORT_DATA ConnectData;
ULONG ConnectDataLength = sizeof ConnectData;
SECURITY_QUALITY_OF_SERVICE Sqos;
NTSTATUS Status;
TRACE;
/*
* Initialize the connection data object before
* calling PSXSS.
*/
ConnectData.ConnectionType = PSX_CONNECTION_TYPE_TERMINAL;
ConnectData.Version = PSX_LPC_PROTOCOL_VERSION;
/*
* Try connecting to \POSIX+\SessionPort.
*/
Status = NtConnectPort (
& Session.ServerPort.Handle,
& Session.ServerPort.Name,
& Sqos,
NULL,
NULL,
0,
& ConnectData,
& ConnectDataLength
);
if (STATUS_SUCCESS != Status)
{
vtprintf ("%s: %s: NtConnectPort failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
Session.Identifier = ConnectData.PortIdentifier;
return STATUS_SUCCESS;
}
/**********************************************************************
* InitializeSsIoChannel PRIVATE
*
* DESCRIPTION
* Create our objects in the system name space
* (CreateSessionObjects) and then connect to the session port
* (CreateControChannel).
*/
PRIVATE NTSTATUS STDCALL InitializeSsIoChannel (VOID)
{
NTSTATUS Status = STATUS_SUCCESS;
DWORD Pid = GetCurrentProcessId();
TRACE;
Status = CreateSessionObjects (Pid);
if (STATUS_SUCCESS != Status)
{
vtprintf ("%s: %s: CreateSessionObjects failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
Status = CreateTerminalToPsxChannel ();
if (STATUS_SUCCESS != Status)
{
vtprintf ("%s: %s: CreateTerminalToPsxChannel failed with %08x\n",
MyName, __FUNCTION__, Status);
return Status;
}
return STATUS_SUCCESS;
}
/**********************************************************************
* PsxCreateLeaderProcess/1 PRIVATE
*
* DESCRIPTION
* Create a new PSXSS process.
*/
PRIVATE NTSTATUS STDCALL PsxCreateLeaderProcess (char * Command)
{
TRACE;
if (NULL == Command)
{
Command = "/bin/sh";
}
/* TODO: request PSXSS to init the process slot */
return STATUS_NOT_IMPLEMENTED;
}
/**********************************************************************
* PrintInformationProcess/0
*
* DESCRIPTION
*/
PRIVATE VOID STDCALL PrintInformationProcess (VOID)
{
TRACE;
vtputs ("Leader:");
vtprintf (" UniqueProcess %08x\n", Session.Client.UniqueProcess);
vtprintf (" UniqueThread %08x\n", Session.Client.UniqueThread);
}
/**********************************************************************
* PostMortem/0
*
* DESCRIPTION
*/
PRIVATE INT STDCALL PostMortem (VOID)
{
DWORD ExitCode;
TRACE;
PrintInformationProcess ();
if (TRUE == GetExitCodeProcess (Session.Client.UniqueProcess, & ExitCode))
{
vtprintf (" ExitCode %d\n", ExitCode);
}
return 0;
}
/**********************************************************************
* InputTerminalEmulator/0
*
* DESCRIPTION
* Process user terminal input.
*
* NOTE
* This code is run in the main thread.
*/
PRIVATE BOOL STDCALL InputTerminalEmulator (VOID)
{
HANDLE StandardInput;
INPUT_RECORD InputRecord [INPUT_QUEUE_SIZE];
DWORD NumberOfEventsRead = 0;
INT CurrentEvent;
TRACE;
StandardInput = GetStdHandle (STD_INPUT_HANDLE);
if (INVALID_HANDLE_VALUE == StandardInput)
{
return FALSE;
}
while ((TRUE == Session.SsLinkIsActive) &&
ReadConsoleInput (
StandardInput,
InputRecord,
(sizeof InputRecord) / sizeof (INPUT_RECORD),
& NumberOfEventsRead
))
{
for ( CurrentEvent = 0;
(CurrentEvent < NumberOfEventsRead);
CurrentEvent ++
)
{
switch (InputRecord [CurrentEvent].EventType)
{
case KEY_EVENT:
OutPort (& InputRecord [CurrentEvent].Event.KeyEvent.uChar.AsciiChar, 1);
break;
case MOUSE_EVENT:
/* TODO: send a sequence of move cursor codes */
/* InputRecord [CurrentEvent].Event.MouseEvent; */
break;
case WINDOW_BUFFER_SIZE_EVENT:
/* TODO: send a SIGWINCH signal to the leader process. */
/* InputRecord [CurrentEvent].Event.WindowBufferSizeEvent.dwSize; */
break;
/* Next events should be ignored. */
case MENU_EVENT:
vtprintf ("%s: %s: MENU_EVENT received from CSRSS\n", MyName, __FUNCTION__);
case FOCUS_EVENT:
vtprintf ("%s: %s: FOCUS_EVENT received from CSRSS\n", MyName, __FUNCTION__);
break;
}
}
NumberOfEventsRead = 0;
}
return TRUE;
}
/**********************************************************************
* Startup/1
*
* DESCRIPTION
* Initialize the program.
*/
PRIVATE VOID STDCALL Startup (LPSTR Command)
{
NTSTATUS Status;
DWORD ThreadId;
TRACE;
/* PSX process info */
Session.Client.UniqueProcess = INVALID_HANDLE_VALUE;
Session.Client.UniqueThread = INVALID_HANDLE_VALUE;
/* Initialize the VT-100 emulator */
vtInitVT100 ();
/* Connect to PSXSS */
Status = InitializeSsIoChannel ();
if (!NT_SUCCESS(Status))
{
vtprintf ("%s: failed to connect to PSXSS (Status=%08x)!\n",
MyName, Status);
exit (EXIT_FAILURE);
}
/* Create the leading process for this session */
Status = PsxCreateLeaderProcess (Command);
if (!NT_SUCCESS(Status))
{
vtprintf ("%s: failed to create the PSX process (Status=%08x)!\n",
MyName, Status);
exit (EXIT_FAILURE);
}
}
/**********************************************************************
* Shutdown/0 PRIVATE
*
* DESCRIPTION
* Shutdown the program.
*/
PRIVATE INT STDCALL Shutdown (VOID)
{
TRACE;
/* TODO: try exiting cleanly: close any open resource */
/* TODO: notify PSXSS the session is terminating */
RtlDeleteCriticalSection (& Session.Lock);
return PostMortem ();
}
/**********************************************************************
*
* ENTRY POINT PUBLIC
*
*********************************************************************/
int main (int argc, char * argv [])
{
TRACE;
Startup (argv[1]); /* Initialization */
InputTerminalEmulator (); /* Process user input */
return Shutdown ();
}
/* EOF */

View file

@ -0,0 +1,53 @@
#ifndef _CSRTERM_H
#define _CSRTERM_H
/* PSX session: CSR terminal emulator side */
#define NAME_BUFFER_SIZE 64
typedef struct _PSXSS_PORT
{
UNICODE_STRING Name;
WCHAR NameBuffer [NAME_BUFFER_SIZE];
HANDLE Handle;
} PSXSS_PORT, * PPSXSS_PORT;
typedef struct _CSRTERM_SESSION_PORT
{
UNICODE_STRING Name;
WCHAR NameBuffer [NAME_BUFFER_SIZE];
HANDLE Handle;
struct {
HANDLE Handle;
DWORD Id;
} Thread;
} CSRTERM_SESSION_PORT;
typedef struct _CSRTERM_SESSION_SECTION
{
UNICODE_STRING Name;
WCHAR NameBuffer [NAME_BUFFER_SIZE];
HANDLE Handle;
ULONG Size;
PVOID BaseAddress;
ULONG ViewSize;
} CSRTERM_SESSION_SECTION;
typedef struct _CSRTERM_SESSION
{
ULONG Identifier; /* PortID for ServerPort in PSXSS */
PSXSS_PORT ServerPort; /* \POSIX+\SessionPort */
CSRTERM_SESSION_PORT Port; /* \POSIX+\Sessions\P<pid> */
CSRTERM_SESSION_SECTION Section; /* \POSIX+\Sessions\D<pid> */
CLIENT_ID Client;
CRITICAL_SECTION Lock;
BOOL SsLinkIsActive;
} CSRTERM_SESSION, * PCSRTERM_SESSION;
#define LOCK_SESSION RtlEnterCriticalSection(& Session.Lock)
#define UNLOCK_SESSION RtlLeaveCriticalSection(& Session.Lock)
#endif /* ndef _CSRTERM_H */

View file

@ -0,0 +1,38 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "CSR Terminal Emulator for POSIX+\0"
VALUE "FileVersion", RES_STR_FILE_VERSION
VALUE "InternalName", "csrterm\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "csrterm.exe\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,79 @@
$Id: readme.txt,v 1.1 2002/03/17 22:15:39 ea Exp $
csrterm - a CSR client terminal emulator for the POSIX+ subsystem
SYNOPSYS
csrterm [program]
program program to be run in the terminal; if none is given,
the shell for the current user (W32 session's) is
used.
DESCRIPTION
csrterm emulates a DEC VT-100 terminal (on top of the CSRSS
subsystem, hence the name) which is the controlling terminal
for a process [program] running in the context of the PSX
subsystem. csrterm is a Win32 console application, not a PSX
application. The process created by the PSX subsystem on behalf
of csrterm is not the child of the csrterm instance that
requested it. csrterm simply performs terminal I/O in the CSRSS
world (the W32 world!) for [program].
NOTES
The role of csrterm is creating a session in the PSX subsystem
managing any I/O for it. This is how it works:
1. csrterm creates two well known named objects in the system
name space that will allow the PSX subsystem server to build
the I/O channel for the session. To let the PSX subsystem
process recognize the objects, they contain a numeric suffix
which is the process identifier (n) the system gives to each
instance of csrterm:
\POSIX+\Session\Pn LPC port (IPC rendez-vous object)
\POSIX+\Session\Dn section (shared memory object)
csrterm also creates a new thread to manage the calls though
the LPC port. Port Pn is used by the subsystem to control the
terminal which csrterm emulates.
2. csrterm connects to the PSX subsystem session port
\POSIX+\SessionPort
and asks the subsystem to create a new session.
3. The PSX subsystem, if it decides to accept the request, creates
a new session for that calling instance of csrterm (n), and in
turn connects back to the terminal control port
\POSIX+\Session\Pn
4. When csrterm makes the PSX subsystem create the new session, it
also tells the subsystem what program should be the session
leader process. The PSX subsystem creates that process (the
image file to start must be marked IMAGE_SUBSYSTEM_POSIX_GUI or
IMAGE_SUBSYSTEM_POSIX_CUI).
5. The requested process [program] runs in the context of the
PSX subsystem and performs any terminal I/O via the channel
csrterm and the PSX susbstem created.
REVISIONS
2001-05-05 created
2002-03-03 simplified
AUTHOR
Emanuele Aliberti <ea@iol.it>
CREDITS
John L. Miller (johnmil@cs.cmu.edu, johnmil@jprc.com) code for
a basic VT-100 emulator for Win32 consoles is used to process
tc* calls output.
EOF

1124
posix/apps/csrterm/vt100.c Normal file

File diff suppressed because it is too large Load diff

320
posix/apps/csrterm/vt100.h Normal file
View file

@ -0,0 +1,320 @@
/* vt100.h
*
* AUTHOR: John L. Miller, johnmil@cs.cmu.edu / johnmil@jprc.com
* DATE: 8/4/96
*
* Copyright (c) 1996 John L. Miller
*
* Full permission is granted to use, modify and distribute
* this code, provided:
* 1) This comment field is included in its entirity
* 2) No money is charged for any work including or based on
* portions of this code.
*
* If you're a nice person and find this useful, I'd appreciate a
* note letting me know about it. e-mail is usually what spurs me
* on to improve and support software I've written.
*
*/
/* This identifier should be spit back to the computer when a terminal
* id is requested.
*/
#define ANSWERBACK_MESSAGE "vt100"
/* Various terminal-related modes Entries are as follows:
* Identification esc. ID If set, if clear
*/
/* Keyboard action 2 Locked Unlocked */
#define CAPS_MODE 0x00000001
/* Insertion 4 Insert Overwrite */
#define INSERT_MODE 0x00000002
/* Send - Receive 12 Full Echo */
#define FULLDUPLEX_MODE 0x00000004
/* Line feed/New line 20 New line Line feed */
#define NEWLINE_MODE 0x00000008
#define NUM_TERM_ATTR_MODES 9 /* We only track eight '?' escape sequences */
/* Cursor key ?1 Application Cursor */
#define CURSORAPPL_MODE 0x00000010
/* ANSI/VT52 ?2 ANSI VT52 */
#define ANSI_MODE 0x00000020
/* Column ?3 132 80 */
#define COL132_MODE 0x00000040
/* Scrolling ?4 Smooth Jump */
#define SMOOTHSCROLL_MODE 0x00000080
/* Screen ?5 Reverse Normal */
#define REVSCREEN_MODE 0x00000100
/* Origin ?6 Relative Absolute */
#define ORIGINREL_MODE 0x00000200
/* Wraparound ?7 Wrap Truncate */
#define WRAP_MODE 0x00000400
/* Auto key repeat ?8 Repeating No repeat */
#define REPEAT_MODE 0x00000800
/* Print form feed ?18 Yes No */
#define PRINTFF_MODE 0x00001000
/* Print extent ?19 Full screen Scrolling region */
#define PRINTFULLSCR_MODE 0x00002000
/* Keypad application 'Esc =' numeric 'Esc >' */
#define KEYPADNUMERIC_MODE 0x00004000
/* default mode that we start the emulator with */
#define DEFAULT_MODE (NEWLINE_MODE|ANSI_MODE|REPEAT_MODE)
/* This constant is VERY important - the size of the buffer for
* unprocessed vt-100 prints!
*/
#define MAXVTBUFLEN 4096
/* Constants used in place of actual row and column numbers
* for the cursor movement and text erasing and deleting functions.
*/
#define CUR_ROW -999
#define CUR_COL -999
#define ALL_TABS -1999
#define LEFT_EDGE 0
#define RIGHT_EDGE 12000
#define TOP_EDGE 0
#define BOTTOM_EDGE 12000
/* Text attribute definitions; color, font, bold. */
#define NUM_SC_ATTRIBUTES 11
#define SC_RED 0x0001
#define SC_GREEN 0x0002
#define SC_BLUE 0x0004
#define SC_BOLD 0x0010
#define SC_UL 0x0020 /* Underlined */
#define SC_BL 0x0040 /* Blinking */
#define SC_RV 0x0080 /* Reverse video */
#define SC_ASCII 0x0100 /* Normal ASCII (USASCII) */
#define SC_G0 0x0200 /* graphics set G0 */
#define SC_G1 0x0400 /* Graphics set G1 */
#define SC_GRAPHICS 0x0800 /* Good question */
/* forward variable declarations */
extern int termAttrMode[NUM_TERM_ATTR_MODES];
extern int alltermAttrModes;
/* prototypes from vt100.c */
/* functions meant for use outside of the emulator */
int vtputs(char *f);
int vtprintf(char *format, ...);
int vtInitVT100(void);
int vtProcessedTextOut(char *cbuf, int count);
/* Prototype for functions which MUST BE SUPPLIED BY THE BACK END!!! */
/* Back-end specific initialization is performed in this function.
* this is gauranteed to be called before any other requests are made
* of the back end.
*/
/* beInitVT100Terminal() -
*
* This function is called by the VT100 emulator as soon as the
* front-end terminal is initialized. It's responsible for setting
* initial state of the terminal, and initing our many wacky variables.
*/
int beInitVT100Terminal();
/* beAbsoluteCursor -
*
* Given an input row and column, move the cursor to the
* absolute screen coordinates requested. Note that if the
* display window has scrollbars, the column is adjusted
* to take that into account, but the row is not. This allows
* for large scrollback in terminal windows.
*
* ROW must be able to accept CUR_ROW, TOP_EDGE, BOTTOM_EDGE,
* or a row number.
*
* COLUMN must be able to accept CUR_COL, LEFT_EDGE, RIGHT_EDGE,
* or a column number.
*/
int beAbsoluteCursor(int row, int col);
/* beOffsetCursor -
*
* Given an input row and column offset, move the cursor by that
* many positions. For instance, row=0 and column=-1 would move
* the cursor left a single column.
*
* If the cursor can't move the requested amount, results are
* unpredictable.
*/
int beOffsetCursor(int row, int column);
/* beRestoreCursor -
*
* Saved cursor position should be stored in a static
* variable in the back end. This function restores the
* cursor to the position stored in that variable.
*/
int beRestoreCursor(void);
/* beSaveCursor -
*
* The back-end should maintain a static variable with the
* last STORED cursor position in it. This function replaces
* the contents of that variable with the current cursor position.
* The cursor may be restored to this position by using the
* beRestoreCursor function.
*/
int beSaveCursor(void);
/* beGetTextAttributes -
*
* given a pointer to 'fore'ground and 'back'ground ints,
* fill them with a device-independant description of the
* current foreground and background colors, as well as any
* font information in the foreground variable.
*/
int beGetTextAttributes(int *fore, int *back);
/* beSetTextAttributes -
*
* Given a foreground and a background device independant (SC) color and font
* specification, apply these to the display, and save the state in the
* static screen variables.
*
* Note that many font-specific constants (bold/underline/reverse, G0/G1/ASCII)
* are stored ONLY in the foreground specification.
*/
int beSetTextAttributes(int fore, int back);
/* beRawTextOut-
*
* The name of this function is misleading. Given a pointer to
* ascii text and a count of bytes to print, print them to the
* display device. If wrapping is enabled, wrap text. If there is a
* scrolling region set and the cursor is in it,
* scroll only within that region. 'beRawTextOut' means that it's guaranteed
* not to have control sequences within the text.
*/
int beRawTextOut(char *text, int len);
/* beEraseText -
*
* Given a 'from' and a 'to' position in display coordinates,
* this function will fill in all characters between the two
* (inclusive) with spaces. Note that the coordinates do NOT
* specify a rectangle. erasing from (1,1) to (2,2) erases
* all of the first row, and the first two characters of the
* second.
*
* Note that this routine must be able to handle TOP_EDGE,
* BOTTOM_EDGE, LEFT_EDGE, RIGHT_EDGE, CUR_ROW, and CUR_COL
* in the appropriate parameters.
*/
int beEraseText(int rowFrom, int colFrom, int rowTo, int colTo);
/* beDeleteText -
*
* Given a screen cursor 'from' and 'to' position, this function
* will delete all text between the two. Text will be scrolled
* up as appropriate to fill the deleted space. Note that, as in
* beEraseText, the two coordinates don't specify a rectangle, but
* rather a starting position and ending position. In other words,
* deleting from (1,1) to (2,2) should move the text from (2,3) to the
* end of the second row to (1,1), move line 3 up to line 2, and so on.
*
* This function must be able to process TOP_EDGE, BOTTOM_EDGE, LEFT_EDGE,
* RIGHT_EDGE, CUR_ROW, and CUR_COL specifications in the appropriate
* variables as well as regular row and column specifications.
*/
int beDeleteText(int rowFrom, int colFrom, int rowTo, int colTo);
/* beInsertRow -
*
* Given a row number or CUR_ROW, TOP_EDGE or BOTTOM_EDGE as an input,
* this function will scroll all text from the current row down down by one,
* and create a blank row under the cursor.
*/
int beInsertRow(int row);
/* beTransmitText -
*
* Given a pointer to text and byte count, this routine should transmit data
* to whatever host made the request it's responding to. Typically this routin
* should transmit data as though the user had typed it in.
*/
int beTransmitText(char *text, int len);
/* beAdvanceToTab -
*
* This routine will destructively advance the cursor to the
* next set tab, or to the end of the line if there are no
* more tabs to the right of the cursor.
*/
int beAdvanceToTab(void);
/* beClearTab -
*
* This function accepts a constant, and will try to clear tabs
* appropriately. Its argument is either
* ALL_TABS, meaning all tabs should be removed
* CUR_COL, meaning the tab in the current column should be wiped, or
* a column value, meaning if there's a tab there it should be wiped.
*
*/
int beClearTab(int col);
/* beSetScrollingRows -
*
* Given a pair of row numbers, this routine will set the scrolling
* rows to those values. Note that this routine will accept
* TOP_ROW and BOTTOM_ROW as values, meaning that scrolling should
* be enabled for the entire display, regardless of resizing.
*/
int beSetScrollingRows(int fromRow, int toRow);
/* beRingBell -
*
* Ring the system bell once.
*/
int beRingBell(void);
/* beGetTermMode -
*
* Return the value of conTermMode, which is the terminal settings which
* can be queried/set by <esc>[?#h/l.
*/
int beGetTermMode();
/* beSetTermMode -
*
* Set the terminal as requested, assuming we can. Right now we only handle a
* couple of the possible flags, but we store many of the others.
*/
int beSetTermMode(int newMode);