Rename pconsole to winpty.
* This avoids a name conflict with an existing unrelated project. * I think winpty is a better name anyway. (i) It's more obviously Windows-related. (ii) I think it more accurately describes what it does. A "pseudo-console" ought to mirror the console API and allow replacing the implementation built-in to Windows. This project is only trying to provide functionality similar to using the master interface of a Unix pty, but for native console programs.
This commit is contained in:
parent
f1842c63a1
commit
71aa4a59bb
4
Makefile
4
Makefile
@ -20,10 +20,10 @@
|
||||
|
||||
all :
|
||||
cd agent && $(MAKE)
|
||||
cd libpconsole && $(MAKE)
|
||||
cd libwinpty && $(MAKE)
|
||||
cd unix-adapter && $(MAKE)
|
||||
|
||||
clean :
|
||||
cd agent && $(MAKE) clean
|
||||
cd libpconsole && $(MAKE) clean
|
||||
cd libwinpty && $(MAKE) clean
|
||||
cd unix-adapter && $(MAKE) clean
|
||||
|
@ -52,7 +52,7 @@ static long long unixTimeMillis()
|
||||
static const char *getTracingConfig()
|
||||
{
|
||||
if (tracingConfig == NULL) {
|
||||
const char *newTracingConfig = getenv("PCONSOLEDBG");
|
||||
const char *newTracingConfig = getenv("WINPTYDBG");
|
||||
if (newTracingConfig == NULL)
|
||||
newTracingConfig = "";
|
||||
tracingConfig = newTracingConfig;
|
||||
|
@ -21,7 +21,7 @@
|
||||
include ../config.mk
|
||||
include ../config-mingw.mk
|
||||
|
||||
PROGRAM = ../build/pconsole-agent.exe
|
||||
PROGRAM = ../build/winpty-agent.exe
|
||||
|
||||
OBJECTS = \
|
||||
EventLoop.o \
|
||||
|
@ -20,34 +20,34 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PCONSOLE_H
|
||||
#define PCONSOLE_H
|
||||
#ifndef WINPTY_H
|
||||
#define WINPTY_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef PCONSOLE
|
||||
#define PCONSOLE_API __declspec(dllexport)
|
||||
#ifdef WINPTY
|
||||
#define WINPTY_API __declspec(dllexport)
|
||||
#else
|
||||
#define PCONSOLE_API __declspec(dllimport)
|
||||
#define WINPTY_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct pconsole_s pconsole_t;
|
||||
typedef struct winpty_s winpty_t;
|
||||
|
||||
/*
|
||||
* pconsole API.
|
||||
* winpty API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Starts a new pconsole instance with the given size.
|
||||
* Starts a new winpty instance with the given size.
|
||||
*
|
||||
* This function creates a new agent process and connects to it.
|
||||
*/
|
||||
PCONSOLE_API pconsole_t *pconsole_open(int cols, int rows);
|
||||
WINPTY_API winpty_t *winpty_open(int cols, int rows);
|
||||
|
||||
/*
|
||||
* Start a child process. Either (but not both) of appname and cmdline may
|
||||
@ -62,36 +62,36 @@ PCONSOLE_API pconsole_t *pconsole_open(int cols, int rows);
|
||||
*
|
||||
* Returns 0 on success or a Win32 error code on failure.
|
||||
*/
|
||||
PCONSOLE_API int pconsole_start_process(pconsole_t *pc,
|
||||
WINPTY_API int winpty_start_process(winpty_t *pc,
|
||||
const wchar_t *appname,
|
||||
const wchar_t *cmdline,
|
||||
const wchar_t *cwd,
|
||||
const wchar_t *env);
|
||||
|
||||
/*
|
||||
* Returns the exit code of the process started with pconsole_start_process,
|
||||
* Returns the exit code of the process started with winpty_start_process,
|
||||
* or -1 none is available.
|
||||
*/
|
||||
PCONSOLE_API int pconsole_get_exit_code(pconsole_t *pc);
|
||||
WINPTY_API int winpty_get_exit_code(winpty_t *pc);
|
||||
|
||||
/*
|
||||
* Returns an overlapped-mode pipe handle that can be read and written
|
||||
* like a Unix terminal.
|
||||
*/
|
||||
PCONSOLE_API HANDLE pconsole_get_data_pipe(pconsole_t *pc);
|
||||
WINPTY_API HANDLE winpty_get_data_pipe(winpty_t *pc);
|
||||
|
||||
/*
|
||||
* Change the size of the Windows console.
|
||||
*/
|
||||
PCONSOLE_API int pconsole_set_size(pconsole_t *pc, int cols, int rows);
|
||||
WINPTY_API int winpty_set_size(winpty_t *pc, int cols, int rows);
|
||||
|
||||
/*
|
||||
* Closes the pconsole.
|
||||
* Closes the winpty.
|
||||
*/
|
||||
PCONSOLE_API void pconsole_close(pconsole_t *pc);
|
||||
WINPTY_API void winpty_close(winpty_t *pc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PCONSOLE_H */
|
||||
#endif /* WINPTY_H */
|
@ -21,8 +21,8 @@
|
||||
include ../config.mk
|
||||
include ../config-mingw.mk
|
||||
|
||||
LIBRARY = ../build/pconsole.dll
|
||||
OBJECTS = pconsole.o PConsoleDebugClient.o
|
||||
LIBRARY = ../build/winpty.dll
|
||||
OBJECTS = winpty.o WinPtyDebugClient.o
|
||||
LDFLAGS += -shared -static-libgcc -static-libstdc++
|
||||
|
||||
CXXFLAGS += \
|
||||
@ -30,7 +30,7 @@ CXXFLAGS += \
|
||||
-DUNICODE \
|
||||
-D_UNICODE \
|
||||
-D_WIN32_WINNT=0x0501 \
|
||||
-DPCONSOLE \
|
||||
-DWINPTY \
|
||||
-fno-exceptions \
|
||||
-fno-rtti
|
||||
|
@ -18,7 +18,7 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include <pconsole.h>
|
||||
#include <winpty.h>
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -33,17 +33,17 @@
|
||||
|
||||
// TODO: Error handling, handle out-of-memory.
|
||||
|
||||
#define AGENT_EXE L"pconsole-agent.exe"
|
||||
#define AGENT_EXE L"winpty-agent.exe"
|
||||
|
||||
static volatile LONG consoleCounter;
|
||||
|
||||
struct pconsole_s {
|
||||
pconsole_s();
|
||||
struct winpty_s {
|
||||
winpty_s();
|
||||
HANDLE controlPipe;
|
||||
HANDLE dataPipe;
|
||||
};
|
||||
|
||||
pconsole_s::pconsole_s() : controlPipe(NULL), dataPipe(NULL)
|
||||
winpty_s::winpty_s() : controlPipe(NULL), dataPipe(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ static bool connectNamedPipe(HANDLE handle, bool overlapped)
|
||||
return success;
|
||||
}
|
||||
|
||||
static void writePacket(pconsole_t *pc, const WriteBuffer &packet)
|
||||
static void writePacket(winpty_t *pc, const WriteBuffer &packet)
|
||||
{
|
||||
std::string payload = packet.str();
|
||||
int32_t payloadSize = payload.size();
|
||||
@ -125,7 +125,7 @@ static void writePacket(pconsole_t *pc, const WriteBuffer &packet)
|
||||
assert(success && (int32_t)actual == payloadSize);
|
||||
}
|
||||
|
||||
static int32_t readInt32(pconsole_t *pc)
|
||||
static int32_t readInt32(winpty_t *pc)
|
||||
{
|
||||
int32_t result;
|
||||
DWORD actual;
|
||||
@ -228,13 +228,13 @@ static void startAgentProcess(const BackgroundDesktop &desktop,
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
|
||||
PCONSOLE_API pconsole_t *pconsole_open(int cols, int rows)
|
||||
WINPTY_API winpty_t *winpty_open(int cols, int rows)
|
||||
{
|
||||
pconsole_t *pc = new pconsole_t;
|
||||
winpty_t *pc = new winpty_t;
|
||||
|
||||
// Start pipes.
|
||||
std::wstringstream pipeName;
|
||||
pipeName << L"\\\\.\\pipe\\pconsole-" << GetCurrentProcessId()
|
||||
pipeName << L"\\\\.\\pipe\\winpty-" << GetCurrentProcessId()
|
||||
<< L"-" << InterlockedIncrement(&consoleCounter);
|
||||
std::wstring controlPipeName = pipeName.str() + L"-control";
|
||||
std::wstring dataPipeName = pipeName.str() + L"-data";
|
||||
@ -309,7 +309,7 @@ PCONSOLE_API pconsole_t *pconsole_open(int cols, int rows)
|
||||
// they are inherited by any call to CreateProcess with
|
||||
// bInheritHandles==TRUE. To avoid accidental inheritance, the library's
|
||||
// clients would be obligated not to create new processes while a thread
|
||||
// was calling pconsole_open. Moreover, to inherit handles, MSDN seems
|
||||
// was calling winpty_open. Moreover, to inherit handles, MSDN seems
|
||||
// to say that bInheritHandles must be TRUE[*], but I don't want to use a
|
||||
// TRUE bInheritHandles, because I want to avoid leaking handles into the
|
||||
// agent process, especially if the library someday allows creating the
|
||||
@ -329,9 +329,9 @@ PCONSOLE_API pconsole_t *pconsole_open(int cols, int rows)
|
||||
}
|
||||
|
||||
// TODO: We also need to control what desktop the child process is started with.
|
||||
// I think the right default is for this pconsole.dll function to query the
|
||||
// I think the right default is for this winpty.dll function to query the
|
||||
// current desktop and send that to the agent.
|
||||
PCONSOLE_API int pconsole_start_process(pconsole_t *pc,
|
||||
WINPTY_API int winpty_start_process(winpty_t *pc,
|
||||
const wchar_t *appname,
|
||||
const wchar_t *cmdline,
|
||||
const wchar_t *cwd,
|
||||
@ -360,7 +360,7 @@ PCONSOLE_API int pconsole_start_process(pconsole_t *pc,
|
||||
return readInt32(pc);
|
||||
}
|
||||
|
||||
PCONSOLE_API int pconsole_get_exit_code(pconsole_t *pc)
|
||||
WINPTY_API int winpty_get_exit_code(winpty_t *pc)
|
||||
{
|
||||
WriteBuffer packet;
|
||||
packet.putInt(AgentMsg::GetExitCode);
|
||||
@ -368,12 +368,12 @@ PCONSOLE_API int pconsole_get_exit_code(pconsole_t *pc)
|
||||
return readInt32(pc);
|
||||
}
|
||||
|
||||
PCONSOLE_API HANDLE pconsole_get_data_pipe(pconsole_t *pc)
|
||||
WINPTY_API HANDLE winpty_get_data_pipe(winpty_t *pc)
|
||||
{
|
||||
return pc->dataPipe;
|
||||
}
|
||||
|
||||
PCONSOLE_API int pconsole_set_size(pconsole_t *pc, int cols, int rows)
|
||||
WINPTY_API int winpty_set_size(winpty_t *pc, int cols, int rows)
|
||||
{
|
||||
WriteBuffer packet;
|
||||
packet.putInt(AgentMsg::SetSize);
|
||||
@ -383,7 +383,7 @@ PCONSOLE_API int pconsole_set_size(pconsole_t *pc, int cols, int rows)
|
||||
return readInt32(pc);
|
||||
}
|
||||
|
||||
PCONSOLE_API void pconsole_close(pconsole_t *pc)
|
||||
WINPTY_API void winpty_close(winpty_t *pc)
|
||||
{
|
||||
CloseHandle(pc->controlPipe);
|
||||
CloseHandle(pc->dataPipe);
|
@ -21,10 +21,10 @@
|
||||
include ../config.mk
|
||||
include ../config-unix.mk
|
||||
|
||||
PROGRAM = ../build/pconsole.exe
|
||||
PROGRAM = ../build/console.exe
|
||||
OBJECTS = main.o Shared.o
|
||||
CXXFLAGS += -I../include
|
||||
LDFLAGS += ../build/pconsole.dll
|
||||
LDFLAGS += ../build/winpty.dll
|
||||
|
||||
all : $(PROGRAM)
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <pconsole.h>
|
||||
#include <winpty.h>
|
||||
#include "../Shared/DebugClient.h"
|
||||
#include <string>
|
||||
|
||||
@ -97,18 +97,18 @@ static HANDLE createEvent()
|
||||
}
|
||||
|
||||
|
||||
// Connect pconsole overlapped I/O to Cygwin blocking STDOUT_FILENO.
|
||||
// Connect winpty overlapped I/O to Cygwin blocking STDOUT_FILENO.
|
||||
class OutputHandler {
|
||||
public:
|
||||
OutputHandler(HANDLE pconsole);
|
||||
OutputHandler(HANDLE winpty);
|
||||
pthread_t getThread() { return thread; }
|
||||
private:
|
||||
static void *threadProc(void *pvthis);
|
||||
HANDLE pconsole;
|
||||
HANDLE winpty;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
OutputHandler::OutputHandler(HANDLE pconsole) : pconsole(pconsole)
|
||||
OutputHandler::OutputHandler(HANDLE winpty) : winpty(winpty)
|
||||
{
|
||||
pthread_create(&thread, NULL, OutputHandler::threadProc, this);
|
||||
}
|
||||
@ -126,12 +126,12 @@ void *OutputHandler::threadProc(void *pvthis)
|
||||
DWORD amount;
|
||||
memset(&over, 0, sizeof(over));
|
||||
over.hEvent = event;
|
||||
BOOL ret = ReadFile(pthis->pconsole,
|
||||
BOOL ret = ReadFile(pthis->winpty,
|
||||
buffer, bufferSize,
|
||||
&amount,
|
||||
&over);
|
||||
if (!ret && GetLastError() == ERROR_IO_PENDING)
|
||||
ret = GetOverlappedResult(pthis->pconsole, &over, &amount, TRUE);
|
||||
ret = GetOverlappedResult(pthis->winpty, &over, &amount, TRUE);
|
||||
if (!ret || amount == 0)
|
||||
break;
|
||||
// TODO: partial writes?
|
||||
@ -152,18 +152,18 @@ void *OutputHandler::threadProc(void *pvthis)
|
||||
}
|
||||
|
||||
|
||||
// Connect Cygwin non-blocking STDIN_FILENO to pconsole overlapped I/O.
|
||||
// Connect Cygwin non-blocking STDIN_FILENO to winpty overlapped I/O.
|
||||
class InputHandler {
|
||||
public:
|
||||
InputHandler(HANDLE pconsole);
|
||||
InputHandler(HANDLE winpty);
|
||||
pthread_t getThread() { return thread; }
|
||||
private:
|
||||
static void *threadProc(void *pvthis);
|
||||
HANDLE pconsole;
|
||||
HANDLE winpty;
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
InputHandler::InputHandler(HANDLE pconsole) : pconsole(pconsole)
|
||||
InputHandler::InputHandler(HANDLE winpty) : winpty(winpty)
|
||||
{
|
||||
pthread_create(&thread, NULL, InputHandler::threadProc, this);
|
||||
}
|
||||
@ -187,12 +187,12 @@ void *InputHandler::threadProc(void *pvthis)
|
||||
OVERLAPPED over;
|
||||
memset(&over, 0, sizeof(over));
|
||||
over.hEvent = event;
|
||||
BOOL ret = WriteFile(pthis->pconsole,
|
||||
BOOL ret = WriteFile(pthis->winpty,
|
||||
buffer, amount,
|
||||
&written,
|
||||
&over);
|
||||
if (!ret && GetLastError() == ERROR_IO_PENDING)
|
||||
ret = GetOverlappedResult(pthis->pconsole, &over, &written, TRUE);
|
||||
ret = GetOverlappedResult(pthis->winpty, &over, &written, TRUE);
|
||||
// TODO: partial writes?
|
||||
if (!ret || (int)written != amount)
|
||||
break;
|
||||
@ -267,20 +267,20 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
{
|
||||
// Copy the PCONSOLEDBG environment variable from the Cygwin environment
|
||||
// Copy the WINPTYDBG environment variable from the Cygwin environment
|
||||
// to the Win32 environment so the agent will inherit it.
|
||||
const char *dbgvar = getenv("PCONSOLEDBG");
|
||||
const char *dbgvar = getenv("WINPTYDBG");
|
||||
if (dbgvar != NULL) {
|
||||
SetEnvironmentVariableW(L"PCONSOLEDBG", L"1");
|
||||
SetEnvironmentVariableW(L"WINPTYDBG", L"1");
|
||||
}
|
||||
}
|
||||
|
||||
winsize sz;
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &sz);
|
||||
|
||||
pconsole_t *pconsole = pconsole_open(sz.ws_col, sz.ws_row);
|
||||
if (pconsole == NULL) {
|
||||
fprintf(stderr, "Error creating pconsole.\n");
|
||||
winpty_t *winpty = winpty_open(sz.ws_col, sz.ws_row);
|
||||
if (winpty == NULL) {
|
||||
fprintf(stderr, "Error creating winpty.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ int main(int argc, char *argv[])
|
||||
// Start the child process under the console.
|
||||
std::string cmdLine = argvToCommandLine(argc - 1, &argv[1]);
|
||||
wchar_t *cmdLineW = heapMbsToWcs(cmdLine.c_str());
|
||||
int ret = pconsole_start_process(pconsole,
|
||||
int ret = winpty_start_process(winpty,
|
||||
NULL,
|
||||
cmdLineW,
|
||||
NULL,
|
||||
@ -326,8 +326,8 @@ int main(int argc, char *argv[])
|
||||
signalWriteFd = pipeFd[1];
|
||||
}
|
||||
|
||||
OutputHandler outputHandler(pconsole_get_data_pipe(pconsole));
|
||||
InputHandler inputHandler(pconsole_get_data_pipe(pconsole));
|
||||
OutputHandler outputHandler(winpty_get_data_pipe(winpty));
|
||||
InputHandler inputHandler(winpty_get_data_pipe(winpty));
|
||||
|
||||
while (true) {
|
||||
fd_set readfds;
|
||||
@ -355,7 +355,7 @@ int main(int argc, char *argv[])
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &sz2);
|
||||
if (memcmp(&sz, &sz2, sizeof(sz)) != 0) {
|
||||
sz = sz2;
|
||||
pconsole_set_size(pconsole, sz.ws_col, sz.ws_row);
|
||||
winpty_set_size(winpty, sz.ws_col, sz.ws_row);
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,9 +365,9 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
int exitCode = pconsole_get_exit_code(pconsole);
|
||||
int exitCode = winpty_get_exit_code(winpty);
|
||||
|
||||
restoreTerminalMode(mode);
|
||||
// TODO: Call pconsole_close? Shut down one or both I/O threads?
|
||||
// TODO: Call winpty_close? Shut down one or both I/O threads?
|
||||
return exitCode;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user