diff --git a/src/apps/terminal/TermApp.cpp b/src/apps/terminal/TermApp.cpp index fa1b7e86bb..23ac8a4503 100644 --- a/src/apps/terminal/TermApp.cpp +++ b/src/apps/terminal/TermApp.cpp @@ -11,7 +11,7 @@ #include "CodeConv.h" #include "PrefHandler.h" -#include "spawn.h" +//#include "spawn.h" #include "TermBuffer.h" #include "TermWindow.h" #include "TermConst.h" @@ -25,11 +25,10 @@ #include #include -#include +//#include #include #include -#include -#include + // Globals @@ -119,14 +118,8 @@ TermApp::ReadyToRun() void TermApp::Quit() { - if (!sUsageRequested){ - int status; - - kill(-gShPid, SIGHUP); - wait(&status); - + if (!sUsageRequested) _UnregisterTerminal(); - } BApplication::Quit(); } diff --git a/src/apps/terminal/TermParse.cpp b/src/apps/terminal/TermParse.cpp index 6104521dd2..20f10d1152 100644 --- a/src/apps/terminal/TermParse.cpp +++ b/src/apps/terminal/TermParse.cpp @@ -47,12 +47,10 @@ extern int mbcstable[]; /* ESC $ */ #define NPARAM 10 // Max parameters -TermParse::TermParse(int fd, TermWindow *inWinObj, TermView *inViewObj, - CodeConv *inConvObj) +TermParse::TermParse(int fd, TermView *inViewObj, CodeConv *inConvObj) : fFd(fd), fViewObj(inViewObj), - fWinObj(inWinObj), fConvObj(inConvObj), fParseThread(-1), fParseSem(-1), @@ -807,7 +805,7 @@ TermParse::EscParse() switch (mode_char) { case '0': case '2': - fWinObj->SetTitle(string); + fViewObj->Window()->SetTitle(string); break; case '1': break; diff --git a/src/apps/terminal/TermParse.h b/src/apps/terminal/TermParse.h index fa8b0799ea..0441291d36 100644 --- a/src/apps/terminal/TermParse.h +++ b/src/apps/terminal/TermParse.h @@ -39,14 +39,13 @@ class TermView; class CodeConv; -class TermWindow; //PtyReader buffer size. #define READ_BUF_SIZE 2048 class TermParse : public BHandler { public: - TermParse(int fd, TermWindow *inWinObj, TermView *inViewObj, CodeConv *inConvObj); + TermParse(int fd, TermView *inViewObj, CodeConv *inConvObj); ~TermParse(); status_t StartThreads(); @@ -72,7 +71,6 @@ private: int fFd; TermView *fViewObj; - TermWindow *fWinObj; CodeConv *fConvObj; thread_id fParseThread; diff --git a/src/apps/terminal/TermView.cpp b/src/apps/terminal/TermView.cpp index bb47b25694..f0d86569a9 100644 --- a/src/apps/terminal/TermView.cpp +++ b/src/apps/terminal/TermView.cpp @@ -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), - fTerminalFd(fd), + fShell(NULL), fFontWidth(0), fFontHeight(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 void TermView::GetFontSize(int* _width, int* _height) @@ -1010,11 +1029,7 @@ TermView::UpdateSIGWINCH() ScrollTo(0, fTop); ResizeScrBarRange(); - struct winsize ws; - ws.ws_row = fTermRows; - ws.ws_col = fTermColumns; - ioctl(fTerminalFd, TIOCSWINSZ, &ws); - kill(-gShPid, SIGWINCH); + fShell->UpdateWindowSize(fTermRows, fTermColumns); fFrameResized = 0; if (fScrRegionSet == 0) @@ -1033,11 +1048,11 @@ TermView::DeviceStatusReport(int n) switch (n) { case 5: len = sprintf(sbuf,"\033[0n") ; - write(fTerminalFd, sbuf, len); + fShell->Write(sbuf, len); break ; case 6: len = sprintf(sbuf,"\033[%d;%dR", fTermRows, fTermColumns) ; - write(fTerminalFd, sbuf, len); + fShell->Write(sbuf, len); break ; default: return; @@ -1210,10 +1225,10 @@ TermView::KeyDown(const char *bytes, int32 numBytes) // If bytes[0] equal intr charactor, // send signal to shell process group. - tcgetattr(fTerminalFd, &tio); + fShell->GetAttr(tio); if (*bytes == tio.c_cc[VINTR]) { if (tio.c_lflag & ISIG) - kill(-gShPid, SIGINT); + fShell->Signal(SIGINT); } // Terminal changes RET, ENTER, F1...F12, and ARROW key code. @@ -1224,24 +1239,24 @@ TermView::KeyDown(const char *bytes, int32 numBytes) case B_RETURN: c = 0x0d; if (key == RETURN_KEY || key == ENTER_KEY) { - write(fTerminalFd, &c, 1); + fShell->Write(&c, 1); return; } else { - write(fTerminalFd, bytes, numBytes); + fShell->Write(bytes, numBytes); return; } break; case B_LEFT_ARROW: 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; } break; case B_RIGHT_ARROW: 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; } break; @@ -1256,7 +1271,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes) } 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; } break; @@ -1269,21 +1284,21 @@ TermView::KeyDown(const char *bytes, int32 numBytes) } 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; } break; case B_INSERT: 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; } break; case B_HOME: 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; } break; @@ -1298,7 +1313,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes) } 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; } break; @@ -1311,14 +1326,14 @@ TermView::KeyDown(const char *bytes, int32 numBytes) } 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; } break; case B_END: 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; } break; @@ -1326,7 +1341,7 @@ TermView::KeyDown(const char *bytes, int32 numBytes) case B_FUNCTION_KEY: for (c = 0; c < 12; c++) { if (key == function_keycode_table[c]) { - write(fTerminalFd, function_key_char_table[c], 5); + fShell->Write(function_key_char_table[c], 5); return; } } @@ -1341,12 +1356,12 @@ TermView::KeyDown(const char *bytes, int32 numBytes) if (GetEncoding() != M_UTF8) { int cnum = fCodeConv->ConvertFromInternal(bytes, numBytes, (char *)dstbuf, GetEncoding()); - write(fTerminalFd, dstbuf, cnum); + fShell->Write(dstbuf, cnum); return; } } - write(fTerminalFd, bytes, numBytes); + fShell->Write(bytes, numBytes); } @@ -1428,7 +1443,7 @@ TermView::MessageReceived(BMessage *msg) case MENU_CLEAR_ALL: DoClearAll(); - write(fTerminalFd, ctrl_l, 1); + fShell->Write(ctrl_l, 1); break; case MSGRUN_CURSOR: @@ -1589,10 +1604,10 @@ TermView::WritePTY(const uchar *text, int numBytes) uchar *destBuffer = (uchar *)malloc(numBytes * 3); numBytes = fCodeConv->ConvertFromInternal((char*)text, numBytes, (char*)destBuffer, GetEncoding()); - write(fTerminalFd, destBuffer, numBytes); + fShell->Write(destBuffer, numBytes); free(destBuffer); } else { - write(fTerminalFd, text, numBytes); + fShell->Write(text, numBytes); } } diff --git a/src/apps/terminal/TermView.h b/src/apps/terminal/TermView.h index 8489a7193d..ad18267727 100644 --- a/src/apps/terminal/TermView.h +++ b/src/apps/terminal/TermView.h @@ -44,7 +44,6 @@ #define CUROFF 0 #define CURON 1 -#define VIEW_THR_CODE 'vtcd' #define MOUSE_THR_CODE 'mtcd' #define RECT_BUF_SIZE 32 @@ -95,12 +94,16 @@ class CodeConv; class BPopUpMenu; class BScrollBar; class BString; +class Shell; class TermView : public BView { public: - TermView(BRect frame, CodeConv *inCodeConv, int fd); + TermView(BRect frame, CodeConv *inCodeConv); ~TermView(); + status_t AttachShell(Shell *shell); + void DetachShell(); + void SetTermFont(const BFont *halfFont, const BFont *fullFont); void GetFontSize(int *width, int *height); BRect SetTermSize(int rows, int cols, bool flag); @@ -225,7 +228,7 @@ class TermView : public BView { bool CheckSelectedRegion(const CurPos &pos); inline void Redraw(int, int, int, int); - int fTerminalFd; + Shell *fShell; // Font and Width BFont fHalfFont; diff --git a/src/apps/terminal/TermWindow.cpp b/src/apps/terminal/TermWindow.cpp index 2ad54d88aa..1fc19bd81a 100644 --- a/src/apps/terminal/TermWindow.cpp +++ b/src/apps/terminal/TermWindow.cpp @@ -56,7 +56,7 @@ extern PrefHandler *gTermPref; TermWindow::TermWindow(BRect frame, const char* title, const char *command) : BWindow(frame, title, B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE|B_QUIT_ON_WINDOW_CLOSE), - fPfd(-1), + fShell(NULL), fTermParse(NULL), fMenubar(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) const char *encoding = longname2shortname(gTermPref->getString(PREF_TEXT_ENCODING)); - fPfd = spawn_shell(rows, cols, command, encoding); - if (fPfd < 0) - throw fPfd; + fShell = new Shell(); + status_t status = fShell->Open(rows, cols, command, encoding); + if (status < 0) + throw status; InitWindow(); } @@ -106,7 +107,9 @@ TermWindow::TermWindow(BRect frame, const char* title, const char *command) TermWindow::~TermWindow() { - close(fPfd); + fTermView->DetachShell(); + + delete fShell; delete fTermParse; delete fCodeConv; if (fPrefWindow) @@ -159,7 +162,9 @@ TermWindow::InitWindow() textframe.top = fMenubar->Bounds().bottom + 1.0; 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. @@ -214,7 +219,7 @@ TermWindow::InitWindow() // Initialize TermParse 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) return; @@ -463,7 +468,7 @@ TermWindow::MessageReceived(BMessage *message) } else if (!strcmp("tty", spe.FindString("property", i))) { BMessage reply(B_REPLY); - reply.AddString("result", ttyname(fPfd)); + reply.AddString("result", fShell->TTYName()); message->SendReply(&reply); } else { BWindow::MessageReceived(message); diff --git a/src/apps/terminal/TermWindow.h b/src/apps/terminal/TermWindow.h index 969b379a7d..43a806ea53 100644 --- a/src/apps/terminal/TermWindow.h +++ b/src/apps/terminal/TermWindow.h @@ -45,7 +45,7 @@ class TermParse; class CodeConv; class PrefWindow; class FindWindow; - +class Shell; class TermWindow : public BWindow { public: @@ -74,7 +74,7 @@ class TermWindow : public BWindow { /* * data member */ - int fPfd; + Shell *fShell; TermParse *fTermParse; BMenuBar *fMenubar; BMenu *fFilemenu, *fEditmenu, *fEncodingmenu, *fHelpmenu, *fFontMenu, *fWindowSizeMenu, *fNewFontMenu; diff --git a/src/apps/terminal/spawn.cpp b/src/apps/terminal/spawn.cpp index 84c9319288..df0cdcf167 100644 --- a/src/apps/terminal/spawn.cpp +++ b/src/apps/terminal/spawn.cpp @@ -30,20 +30,21 @@ */ #include -#include -#include -#include -#include +#include +#include +#include #include +#include #include #include -#include -#include -#include -#include +#include #include +#include +#include #include -#include +#include + +#include #include "TermConst.h" #include "spawn.h" @@ -53,18 +54,20 @@ extern PrefHandler *gTermPref; /* default shell command and options. */ #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'" "'Use Default Shell' 'Abort'"; /* - * Set environment varriable. + * Set environment variable. */ - #if !defined(__HAIKU__) || defined(HAIKU_TARGET_PLATFORM_LIBBE_TEST) -int + +extern char **environ; + +static int setenv(const char *var, const char *value, bool overwrite) { int envindex = 0; @@ -110,9 +113,9 @@ typedef struct #define PTY_NG 1 /* pty open or set termios NG */ #define PTY_WS 2 /* pty need WINSIZE (row and col ) */ -/* global variables */ -pid_t gShPid; + +static pid_t sShPid; 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) { 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); /* Fork a child process. */ - if ((gShPid = fork()) < 0) { + if ((sShPid = fork()) < 0) { close(master); return -1; } @@ -188,7 +191,7 @@ spawn_shell(int row, int col, const char *command, const char *coding) handshake_t handshake; - if (gShPid == 0) { + if (sShPid == 0) { // Now in child process. /* @@ -443,7 +446,7 @@ spawn_shell(int row, int col, const char *command, const char *coding) handshake.row = row; handshake.col = col; handshake.status = PTY_WS; - send_handshake_message(gShPid, handshake); + send_handshake_message(sShPid, handshake); break; } } @@ -451,3 +454,116 @@ spawn_shell(int row, int col, const char *command, const char *coding) 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; +} + diff --git a/src/apps/terminal/spawn.h b/src/apps/terminal/spawn.h index b1b375a4d3..258e0a41d5 100644 --- a/src/apps/terminal/spawn.h +++ b/src/apps/terminal/spawn.h @@ -80,14 +80,30 @@ #define APC 0x9F #define RDEL 0xFF -/* - * Prototype: - */ -int spawn_shell (int, int, const char *, const char *); -void Setenv (const char *, const char *); +class Shell { +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 */