Encapsulated low level terminal stuff into a Shell class, which also

supersedes spawn_shell(). Removed window parameter from TermParse. Since 
we already have a pointer to the view, we just call Window() on it (only 
used in one place, no need to save a pointer). Other cleanups. 


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21628 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini 2007-07-17 07:58:37 +00:00
parent ca210f74f1
commit f3d05c8b3a
9 changed files with 229 additions and 85 deletions

View File

@ -11,7 +11,7 @@
#include "CodeConv.h" #include "CodeConv.h"
#include "PrefHandler.h" #include "PrefHandler.h"
#include "spawn.h" //#include "spawn.h"
#include "TermBuffer.h" #include "TermBuffer.h"
#include "TermWindow.h" #include "TermWindow.h"
#include "TermConst.h" #include "TermConst.h"
@ -25,11 +25,10 @@
#include <String.h> #include <String.h>
#include <TextView.h> #include <TextView.h>
#include <signal.h> //#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
// Globals // Globals
@ -119,14 +118,8 @@ TermApp::ReadyToRun()
void void
TermApp::Quit() TermApp::Quit()
{ {
if (!sUsageRequested){ if (!sUsageRequested)
int status;
kill(-gShPid, SIGHUP);
wait(&status);
_UnregisterTerminal(); _UnregisterTerminal();
}
BApplication::Quit(); BApplication::Quit();
} }

View File

@ -47,12 +47,10 @@ extern int mbcstable[]; /* ESC $ */
#define NPARAM 10 // Max parameters #define NPARAM 10 // Max parameters
TermParse::TermParse(int fd, TermWindow *inWinObj, TermView *inViewObj, TermParse::TermParse(int fd, TermView *inViewObj, CodeConv *inConvObj)
CodeConv *inConvObj)
: :
fFd(fd), fFd(fd),
fViewObj(inViewObj), fViewObj(inViewObj),
fWinObj(inWinObj),
fConvObj(inConvObj), fConvObj(inConvObj),
fParseThread(-1), fParseThread(-1),
fParseSem(-1), fParseSem(-1),
@ -807,7 +805,7 @@ TermParse::EscParse()
switch (mode_char) { switch (mode_char) {
case '0': case '0':
case '2': case '2':
fWinObj->SetTitle(string); fViewObj->Window()->SetTitle(string);
break; break;
case '1': case '1':
break; break;

View File

@ -39,14 +39,13 @@
class TermView; class TermView;
class CodeConv; class CodeConv;
class TermWindow;
//PtyReader buffer size. //PtyReader buffer size.
#define READ_BUF_SIZE 2048 #define READ_BUF_SIZE 2048
class TermParse : public BHandler { class TermParse : public BHandler {
public: public:
TermParse(int fd, TermWindow *inWinObj, TermView *inViewObj, CodeConv *inConvObj); TermParse(int fd, TermView *inViewObj, CodeConv *inConvObj);
~TermParse(); ~TermParse();
status_t StartThreads(); status_t StartThreads();
@ -72,7 +71,6 @@ private:
int fFd; int fFd;
TermView *fViewObj; TermView *fViewObj;
TermWindow *fWinObj;
CodeConv *fConvObj; CodeConv *fConvObj;
thread_id fParseThread; thread_id fParseThread;

View File

@ -63,9 +63,9 @@ const static rgb_color kTermColorTable[16] = {
}; };
TermView::TermView(BRect frame, CodeConv *inCodeConv, int fd) TermView::TermView(BRect frame, CodeConv *inCodeConv)
: BView(frame, "termview", B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS), : BView(frame, "termview", B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS),
fTerminalFd(fd), fShell(NULL),
fFontWidth(0), fFontWidth(0),
fFontHeight(0), fFontHeight(0),
fFontAscent(0), fFontAscent(0),
@ -122,6 +122,25 @@ TermView::~TermView()
} }
status_t
TermView::AttachShell(Shell *shell)
{
if (shell == NULL)
return B_BAD_VALUE;
fShell = shell;
return B_OK;
}
void
TermView::DetachShell()
{
fShell = NULL;
}
//! Get width and height for terminal font //! Get width and height for terminal font
void void
TermView::GetFontSize(int* _width, int* _height) TermView::GetFontSize(int* _width, int* _height)
@ -1010,11 +1029,7 @@ TermView::UpdateSIGWINCH()
ScrollTo(0, fTop); ScrollTo(0, fTop);
ResizeScrBarRange(); ResizeScrBarRange();
struct winsize ws; fShell->UpdateWindowSize(fTermRows, fTermColumns);
ws.ws_row = fTermRows;
ws.ws_col = fTermColumns;
ioctl(fTerminalFd, TIOCSWINSZ, &ws);
kill(-gShPid, SIGWINCH);
fFrameResized = 0; fFrameResized = 0;
if (fScrRegionSet == 0) if (fScrRegionSet == 0)
@ -1033,11 +1048,11 @@ TermView::DeviceStatusReport(int n)
switch (n) { switch (n) {
case 5: case 5:
len = sprintf(sbuf,"\033[0n") ; len = sprintf(sbuf,"\033[0n") ;
write(fTerminalFd, sbuf, len); fShell->Write(sbuf, len);
break ; break ;
case 6: case 6:
len = sprintf(sbuf,"\033[%d;%dR", fTermRows, fTermColumns) ; len = sprintf(sbuf,"\033[%d;%dR", fTermRows, fTermColumns) ;
write(fTerminalFd, sbuf, len); fShell->Write(sbuf, len);
break ; break ;
default: default:
return; return;
@ -1210,10 +1225,10 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
// If bytes[0] equal intr charactor, // If bytes[0] equal intr charactor,
// send signal to shell process group. // send signal to shell process group.
tcgetattr(fTerminalFd, &tio); fShell->GetAttr(tio);
if (*bytes == tio.c_cc[VINTR]) { if (*bytes == tio.c_cc[VINTR]) {
if (tio.c_lflag & ISIG) if (tio.c_lflag & ISIG)
kill(-gShPid, SIGINT); fShell->Signal(SIGINT);
} }
// Terminal changes RET, ENTER, F1...F12, and ARROW key code. // Terminal changes RET, ENTER, F1...F12, and ARROW key code.
@ -1224,24 +1239,24 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
case B_RETURN: case B_RETURN:
c = 0x0d; c = 0x0d;
if (key == RETURN_KEY || key == ENTER_KEY) { if (key == RETURN_KEY || key == ENTER_KEY) {
write(fTerminalFd, &c, 1); fShell->Write(&c, 1);
return; return;
} else { } else {
write(fTerminalFd, bytes, numBytes); fShell->Write(bytes, numBytes);
return; return;
} }
break; break;
case B_LEFT_ARROW: case B_LEFT_ARROW:
if (key == LEFT_ARROW_KEY) { if (key == LEFT_ARROW_KEY) {
write(fTerminalFd, LEFT_ARROW_KEY_CODE, sizeof(LEFT_ARROW_KEY_CODE)-1); fShell->Write(LEFT_ARROW_KEY_CODE, sizeof(LEFT_ARROW_KEY_CODE)-1);
return; return;
} }
break; break;
case B_RIGHT_ARROW: case B_RIGHT_ARROW:
if (key == RIGHT_ARROW_KEY) { if (key == RIGHT_ARROW_KEY) {
write(fTerminalFd, RIGHT_ARROW_KEY_CODE, sizeof(RIGHT_ARROW_KEY_CODE)-1); fShell->Write(RIGHT_ARROW_KEY_CODE, sizeof(RIGHT_ARROW_KEY_CODE)-1);
return; return;
} }
break; break;
@ -1256,7 +1271,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
} }
if (key == UP_ARROW_KEY) { if (key == UP_ARROW_KEY) {
write(fTerminalFd, UP_ARROW_KEY_CODE, sizeof(UP_ARROW_KEY_CODE)-1); fShell->Write(UP_ARROW_KEY_CODE, sizeof(UP_ARROW_KEY_CODE)-1);
return; return;
} }
break; break;
@ -1269,21 +1284,21 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
} }
if (key == DOWN_ARROW_KEY) { if (key == DOWN_ARROW_KEY) {
write(fTerminalFd, DOWN_ARROW_KEY_CODE, sizeof(DOWN_ARROW_KEY_CODE)-1); fShell->Write(DOWN_ARROW_KEY_CODE, sizeof(DOWN_ARROW_KEY_CODE)-1);
return; return;
} }
break; break;
case B_INSERT: case B_INSERT:
if (key == INSERT_KEY) { if (key == INSERT_KEY) {
write(fTerminalFd, INSERT_KEY_CODE, sizeof(INSERT_KEY_CODE)-1); fShell->Write(INSERT_KEY_CODE, sizeof(INSERT_KEY_CODE)-1);
return; return;
} }
break; break;
case B_HOME: case B_HOME:
if (key == HOME_KEY) { if (key == HOME_KEY) {
write(fTerminalFd, HOME_KEY_CODE, sizeof(HOME_KEY_CODE)-1); fShell->Write(HOME_KEY_CODE, sizeof(HOME_KEY_CODE)-1);
return; return;
} }
break; break;
@ -1298,7 +1313,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
} }
if (key == PAGE_UP_KEY) { if (key == PAGE_UP_KEY) {
write(fTerminalFd, PAGE_UP_KEY_CODE, sizeof(PAGE_UP_KEY_CODE)-1); fShell->Write(PAGE_UP_KEY_CODE, sizeof(PAGE_UP_KEY_CODE)-1);
return; return;
} }
break; break;
@ -1311,14 +1326,14 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
} }
if (key == PAGE_DOWN_KEY) { if (key == PAGE_DOWN_KEY) {
write(fTerminalFd, PAGE_DOWN_KEY_CODE, sizeof(PAGE_DOWN_KEY_CODE)-1); fShell->Write(PAGE_DOWN_KEY_CODE, sizeof(PAGE_DOWN_KEY_CODE)-1);
return; return;
} }
break; break;
case B_END: case B_END:
if (key == END_KEY) { if (key == END_KEY) {
write(fTerminalFd, END_KEY_CODE, sizeof(END_KEY_CODE)-1); fShell->Write(END_KEY_CODE, sizeof(END_KEY_CODE)-1);
return; return;
} }
break; break;
@ -1326,7 +1341,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
case B_FUNCTION_KEY: case B_FUNCTION_KEY:
for (c = 0; c < 12; c++) { for (c = 0; c < 12; c++) {
if (key == function_keycode_table[c]) { if (key == function_keycode_table[c]) {
write(fTerminalFd, function_key_char_table[c], 5); fShell->Write(function_key_char_table[c], 5);
return; return;
} }
} }
@ -1341,12 +1356,12 @@ TermView::KeyDown(const char *bytes, int32 numBytes)
if (GetEncoding() != M_UTF8) { if (GetEncoding() != M_UTF8) {
int cnum = fCodeConv->ConvertFromInternal(bytes, numBytes, int cnum = fCodeConv->ConvertFromInternal(bytes, numBytes,
(char *)dstbuf, GetEncoding()); (char *)dstbuf, GetEncoding());
write(fTerminalFd, dstbuf, cnum); fShell->Write(dstbuf, cnum);
return; return;
} }
} }
write(fTerminalFd, bytes, numBytes); fShell->Write(bytes, numBytes);
} }
@ -1428,7 +1443,7 @@ TermView::MessageReceived(BMessage *msg)
case MENU_CLEAR_ALL: case MENU_CLEAR_ALL:
DoClearAll(); DoClearAll();
write(fTerminalFd, ctrl_l, 1); fShell->Write(ctrl_l, 1);
break; break;
case MSGRUN_CURSOR: case MSGRUN_CURSOR:
@ -1589,10 +1604,10 @@ TermView::WritePTY(const uchar *text, int numBytes)
uchar *destBuffer = (uchar *)malloc(numBytes * 3); uchar *destBuffer = (uchar *)malloc(numBytes * 3);
numBytes = fCodeConv->ConvertFromInternal((char*)text, numBytes, numBytes = fCodeConv->ConvertFromInternal((char*)text, numBytes,
(char*)destBuffer, GetEncoding()); (char*)destBuffer, GetEncoding());
write(fTerminalFd, destBuffer, numBytes); fShell->Write(destBuffer, numBytes);
free(destBuffer); free(destBuffer);
} else { } else {
write(fTerminalFd, text, numBytes); fShell->Write(text, numBytes);
} }
} }

View File

@ -44,7 +44,6 @@
#define CUROFF 0 #define CUROFF 0
#define CURON 1 #define CURON 1
#define VIEW_THR_CODE 'vtcd'
#define MOUSE_THR_CODE 'mtcd' #define MOUSE_THR_CODE 'mtcd'
#define RECT_BUF_SIZE 32 #define RECT_BUF_SIZE 32
@ -95,12 +94,16 @@ class CodeConv;
class BPopUpMenu; class BPopUpMenu;
class BScrollBar; class BScrollBar;
class BString; class BString;
class Shell;
class TermView : public BView { class TermView : public BView {
public: public:
TermView(BRect frame, CodeConv *inCodeConv, int fd); TermView(BRect frame, CodeConv *inCodeConv);
~TermView(); ~TermView();
status_t AttachShell(Shell *shell);
void DetachShell();
void SetTermFont(const BFont *halfFont, const BFont *fullFont); void SetTermFont(const BFont *halfFont, const BFont *fullFont);
void GetFontSize(int *width, int *height); void GetFontSize(int *width, int *height);
BRect SetTermSize(int rows, int cols, bool flag); BRect SetTermSize(int rows, int cols, bool flag);
@ -225,7 +228,7 @@ class TermView : public BView {
bool CheckSelectedRegion(const CurPos &pos); bool CheckSelectedRegion(const CurPos &pos);
inline void Redraw(int, int, int, int); inline void Redraw(int, int, int, int);
int fTerminalFd; Shell *fShell;
// Font and Width // Font and Width
BFont fHalfFont; BFont fHalfFont;

View File

@ -56,7 +56,7 @@ extern PrefHandler *gTermPref;
TermWindow::TermWindow(BRect frame, const char* title, const char *command) TermWindow::TermWindow(BRect frame, const char* title, const char *command)
: BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE), : BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE),
fPfd(-1), fShell(NULL),
fTermParse(NULL), fTermParse(NULL),
fMenubar(NULL), fMenubar(NULL),
fFilemenu(NULL), fFilemenu(NULL),
@ -96,9 +96,10 @@ TermWindow::TermWindow(BRect frame, const char* title, const char *command)
// Get encoding name (setenv TTYPE in spawn_shell functions) // Get encoding name (setenv TTYPE in spawn_shell functions)
const char *encoding = longname2shortname(gTermPref->getString(PREF_TEXT_ENCODING)); const char *encoding = longname2shortname(gTermPref->getString(PREF_TEXT_ENCODING));
fPfd = spawn_shell(rows, cols, command, encoding); fShell = new Shell();
if (fPfd < 0) status_t status = fShell->Open(rows, cols, command, encoding);
throw fPfd; if (status < 0)
throw status;
InitWindow(); InitWindow();
} }
@ -106,7 +107,9 @@ TermWindow::TermWindow(BRect frame, const char* title, const char *command)
TermWindow::~TermWindow() TermWindow::~TermWindow()
{ {
close(fPfd); fTermView->DetachShell();
delete fShell;
delete fTermParse; delete fTermParse;
delete fCodeConv; delete fCodeConv;
if (fPrefWindow) if (fPrefWindow)
@ -159,7 +162,9 @@ TermWindow::InitWindow()
textframe.top = fMenubar->Bounds().bottom + 1.0; textframe.top = fMenubar->Bounds().bottom + 1.0;
fCodeConv = new CodeConv(); fCodeConv = new CodeConv();
fTermView = new TermView(Bounds(), fCodeConv, fPfd); fTermView = new TermView(Bounds(), fCodeConv);
fTermView->AttachShell(fShell);
/* /*
* MuTerm has two views. BaseView is window base view. * MuTerm has two views. BaseView is window base view.
@ -214,7 +219,7 @@ TermWindow::InitWindow()
// Initialize TermParse // Initialize TermParse
SetEncoding(longname2id(gTermPref->getString(PREF_TEXT_ENCODING))); SetEncoding(longname2id(gTermPref->getString(PREF_TEXT_ENCODING)));
fTermParse = new TermParse(fPfd, this, fTermView, fCodeConv); fTermParse = new TermParse(fShell->FD(), fTermView, fCodeConv);
if (fTermParse->StartThreads() < B_OK) if (fTermParse->StartThreads() < B_OK)
return; return;
@ -463,7 +468,7 @@ TermWindow::MessageReceived(BMessage *message)
} }
else if (!strcmp("tty", spe.FindString("property", i))) { else if (!strcmp("tty", spe.FindString("property", i))) {
BMessage reply(B_REPLY); BMessage reply(B_REPLY);
reply.AddString("result", ttyname(fPfd)); reply.AddString("result", fShell->TTYName());
message->SendReply(&reply); message->SendReply(&reply);
} else { } else {
BWindow::MessageReceived(message); BWindow::MessageReceived(message);

View File

@ -45,7 +45,7 @@ class TermParse;
class CodeConv; class CodeConv;
class PrefWindow; class PrefWindow;
class FindWindow; class FindWindow;
class Shell;
class TermWindow : public BWindow { class TermWindow : public BWindow {
public: public:
@ -74,7 +74,7 @@ class TermWindow : public BWindow {
/* /*
* data member * data member
*/ */
int fPfd; Shell *fShell;
TermParse *fTermParse; TermParse *fTermParse;
BMenuBar *fMenubar; BMenuBar *fMenubar;
BMenu *fFilemenu, *fEditmenu, *fEncodingmenu, *fHelpmenu, *fFontMenu, *fWindowSizeMenu, *fNewFontMenu; BMenu *fFilemenu, *fEditmenu, *fEncodingmenu, *fHelpmenu, *fFontMenu, *fWindowSizeMenu, *fNewFontMenu;

View File

@ -30,20 +30,21 @@
*/ */
#include <dirent.h> #include <dirent.h>
#include <sys/param.h> #include <errno.h>
#include <stdio.h> #include <fcntl.h>
#include <stdlib.h> #include <signal.h>
#include <unistd.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h> #include <sys/param.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h> #include <time.h>
#include <kernel/OS.h> #include <unistd.h>
#include <OS.h>
#include "TermConst.h" #include "TermConst.h"
#include "spawn.h" #include "spawn.h"
@ -53,18 +54,20 @@ extern PrefHandler *gTermPref;
/* default shell command and options. */ /* default shell command and options. */
#define SHELL_COMMAND "/bin/sh -login" #define SHELL_COMMAND "/bin/sh -login"
extern char **environ;
const char *kSpawnAlertMessage = "alert --stop " "'Cannot execute \"%s\":\n"
const static char *kSpawnAlertMessage = "alert --stop " "'Cannot execute \"%s\":\n"
"\t%s\n'" "\t%s\n'"
"'Use Default Shell' 'Abort'"; "'Use Default Shell' 'Abort'";
/* /*
* Set environment varriable. * Set environment variable.
*/ */
#if !defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST) #if !defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST)
int
extern char **environ;
static int
setenv(const char *var, const char *value, bool overwrite) setenv(const char *var, const char *value, bool overwrite)
{ {
int envindex = 0; int envindex = 0;
@ -110,9 +113,9 @@ typedef struct
#define PTY_NG 1 /* pty open or set termios NG */ #define PTY_NG 1 /* pty open or set termios NG */
#define PTY_WS 2 /* pty need WINSIZE (row and col ) */ #define PTY_WS 2 /* pty need WINSIZE (row and col ) */
/* global variables */
pid_t gShPid;
static pid_t sShPid;
static status_t static status_t
@ -130,7 +133,7 @@ receive_handshake_message(handshake_t& handshake)
} }
int static int
spawn_shell(int row, int col, const char *command, const char *coding) spawn_shell(int row, int col, const char *command, const char *coding)
{ {
signal(SIGTTOU, SIG_IGN); signal(SIGTTOU, SIG_IGN);
@ -180,7 +183,7 @@ spawn_shell(int row, int col, const char *command, const char *coding)
thread_id terminalThread = find_thread(NULL); thread_id terminalThread = find_thread(NULL);
/* Fork a child process. */ /* Fork a child process. */
if ((gShPid = fork()) < 0) { if ((sShPid = fork()) < 0) {
close(master); close(master);
return -1; return -1;
} }
@ -188,7 +191,7 @@ spawn_shell(int row, int col, const char *command, const char *coding)
handshake_t handshake; handshake_t handshake;
if (gShPid == 0) { if (sShPid == 0) {
// Now in child process. // Now in child process.
/* /*
@ -443,7 +446,7 @@ spawn_shell(int row, int col, const char *command, const char *coding)
handshake.row = row; handshake.row = row;
handshake.col = col; handshake.col = col;
handshake.status = PTY_WS; handshake.status = PTY_WS;
send_handshake_message(gShPid, handshake); send_handshake_message(sShPid, handshake);
break; break;
} }
} }
@ -451,3 +454,116 @@ spawn_shell(int row, int col, const char *command, const char *coding)
return (done > 0) ? master : -1; return (done > 0) ? master : -1;
} }
static void
close_shell(int fd)
{
if (fd < 0)
return;
close(fd);
int status;
kill(-sShPid, SIGHUP);
wait(&status);
}
Shell::Shell()
:fFd(-1)
{
}
Shell::~Shell()
{
Close();
}
status_t
Shell::Open(int row, int col, const char *command, const char *coding)
{
fFd = spawn_shell(row, col, command, coding);
if (fFd < 0)
return fFd;
return B_OK;
}
void
Shell::Close()
{
if (fFd >= 0) {
close_shell(fFd);
fFd = -1;
}
}
const char *
Shell::TTYName() const
{
return ttyname(fFd);
}
ssize_t
Shell::Read(void *buffer, size_t numBytes)
{
if (fFd < 0)
return B_NO_INIT;
return read(fFd, buffer, numBytes);
}
ssize_t
Shell::Write(const void *buffer, size_t numBytes)
{
if (fFd < 0)
return B_NO_INIT;
return write(fFd, buffer, numBytes);
}
void
Shell::UpdateWindowSize(int rows, int columns)
{
struct winsize winSize;
winSize.ws_row = rows;
winSize.ws_col = columns;
ioctl(fFd, TIOCSWINSZ, &winSize);
Signal(SIGWINCH);
}
void
Shell::Signal(int signal)
{
kill(-sShPid, signal);
}
status_t
Shell::GetAttr(struct termios &attr)
{
return tcgetattr(fFd, &attr);
}
status_t
Shell::SetAttr(struct termios &attr)
{
return tcsetattr(fFd, TCSANOW, &attr);
}
int
Shell::FD() const
{
return fFd;
}

View File

@ -80,14 +80,30 @@
#define APC 0x9F #define APC 0x9F
#define RDEL 0xFF #define RDEL 0xFF
/*
* Prototype:
*/
int spawn_shell (int, int, const char *, const char *); class Shell {
void Setenv (const char *, const char *); public:
Shell();
~Shell();
extern pid_t gShPid; /* shell process ID */ status_t Open(int row, int col, const char *command, const char *coding);
void Close();
const char * TTYName() const;
ssize_t Read(void *buffer, size_t numBytes);
ssize_t Write(const void *buffer, size_t numBytes);
void UpdateWindowSize(int row, int columns);
void Signal(int signal);
status_t GetAttr(struct termios &attr);
status_t SetAttr(struct termios &attr);
int FD() const;
private:
int fFd;
};
#endif /* SPAWN_H */ #endif /* SPAWN_H */