From 42244cf30eecf46a9e9e45953b0cc05870f765c1 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 14 Jul 2005 23:55:49 +0000 Subject: [PATCH] * Changed MiniTerminal command line arguments. Location and size are now specified via options -l and -s. An arbitrary program can be run in the terminal instead of a shell. * Console::fState was never initialized which could cause the terminal to not print anything. * stdin, -out, and -err were set in MiniView::Start() and in MiniView::ExecuteShell(). Thus resetting them in the latter method after executing the shell had no effect. Removed it in the former method and now reset them after loading, but before resuming the shell. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13676 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/tests/apps/miniterminal/Arguments.cpp | 136 ++++++++++++++++++++++ src/tests/apps/miniterminal/Arguments.h | 32 +++++ src/tests/apps/miniterminal/Console.cpp | 3 +- src/tests/apps/miniterminal/Jamfile | 13 ++- src/tests/apps/miniterminal/MiniApp.cpp | 34 ++---- src/tests/apps/miniterminal/MiniApp.h | 5 +- src/tests/apps/miniterminal/MiniView.cpp | 41 ++++--- src/tests/apps/miniterminal/MiniView.h | 5 +- src/tests/apps/miniterminal/MiniWin.cpp | 10 +- src/tests/apps/miniterminal/MiniWin.h | 3 +- 10 files changed, 227 insertions(+), 55 deletions(-) create mode 100644 src/tests/apps/miniterminal/Arguments.cpp create mode 100644 src/tests/apps/miniterminal/Arguments.h diff --git a/src/tests/apps/miniterminal/Arguments.cpp b/src/tests/apps/miniterminal/Arguments.cpp new file mode 100644 index 0000000000..375fa405dc --- /dev/null +++ b/src/tests/apps/miniterminal/Arguments.cpp @@ -0,0 +1,136 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + +#include + +#include "Arguments.h" + +extern const char *__progname; + +// usage +static const char *kUsage = + "%s [ ... ]\n" + "Starts a terminal with a shell running in it. If is given\n" + "and is an absolute or relative path to an executable, it is run instead\n" + "of the shell. The command line arguments for the program just follow the\n" + "path of the program.\n" + "\n" + "Options:\n" + " -h, --help - print this info text\n" + " -l - open the terminal window at location (, )\n" + " -s - open the terminal window with width and\n" + " height )\n"; + +// application name +const char *kAppName = __progname; + +static void +print_usage(bool error) +{ + fprintf(error ? stderr : stdout, kUsage, kAppName); +} + +static void +print_usage_and_exit(bool error) +{ + print_usage(error); + exit(error ? 0 : 1); +} + +Arguments::Arguments() + : fBounds(50, 50, 630, 435), + fStandardShell(true), + fShellArgumentCount(0), + fShellArguments(NULL) +{ + const char *argv[] = { "/bin/sh", "--login" }; + + _SetShellArguments(2, argv); +} + + +Arguments::~Arguments() +{ + _SetShellArguments(0, NULL); +} + + +void +Arguments::Parse(int argc, const char *const *argv) +{ + int argi = 1; + while (argi < argc) { + const char *arg = argv[argi++]; + + if (*arg == '-') { + if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { + print_usage_and_exit(false); + + } else if (strcmp(arg, "-l") == 0) { + // location + float x, y; + if (argi + 1 >= argc + || sscanf(argv[argi++], "%f", &x) != 1 + || sscanf(argv[argi++], "%f", &y) != 1) { + print_usage_and_exit(true); + } + + fBounds.OffsetTo(x, y); + + } else if (strcmp(arg, "-s") == 0) { + // size + float width, height; + if (argi + 1 >= argc + || sscanf(argv[argi++], "%f", &width) != 1 + || sscanf(argv[argi++], "%f", &height) != 1) { + print_usage_and_exit(true); + } + + fBounds.right = fBounds.left + width; + fBounds.bottom = fBounds.top + height; + + } else { + // illegal option + fprintf(stderr, "Unrecognized option \"%s\"\n", arg); + print_usage_and_exit(true); + } + + } else { + // no option, so the remainder is the shell program with arguments + _SetShellArguments(argc - argi + 1, argv + argi - 1); + argi = argc; + fStandardShell = false; + } + } +} + + +void +Arguments::GetShellArguments(int &argc, const char *const *&argv) const +{ + argc = fShellArgumentCount; + argv = fShellArguments; +} + + +void +Arguments::_SetShellArguments(int argc, const char *const *argv) +{ + // delete old arguments + delete[] fShellArguments; + fShellArguments = NULL; + fShellArgumentCount = 0; + + // copy new ones + if (argc > 0 && argv) { + fShellArguments = new const char*[argc + 1]; + for (int i = 0; i < argc; i++) + fShellArguments[i] = argv[i]; + + fShellArguments[argc] = NULL; + fShellArgumentCount = argc; + } +} + diff --git a/src/tests/apps/miniterminal/Arguments.h b/src/tests/apps/miniterminal/Arguments.h new file mode 100644 index 0000000000..2c36ff1192 --- /dev/null +++ b/src/tests/apps/miniterminal/Arguments.h @@ -0,0 +1,32 @@ +/* + * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. + * Distributed under the terms of the MIT License. + */ + +#ifndef ARGUMENTS_H +#define ARGUMENTS_H + +#include + +class Arguments { +public: + Arguments(); + ~Arguments(); + + void Parse(int argc, const char *const *argv); + + BRect Bounds() const { return fBounds; } + bool StandardShell() const { return fStandardShell; } + void GetShellArguments(int &argc, const char *const *&argv) const; + +private: + void _SetShellArguments(int argc, const char *const *argv); + + BRect fBounds; + bool fStandardShell; + int fShellArgumentCount; + const char **fShellArguments; +}; + + +#endif // ARGUMENTS_H diff --git a/src/tests/apps/miniterminal/Console.cpp b/src/tests/apps/miniterminal/Console.cpp index 717b769044..4700e06dd2 100644 --- a/src/tests/apps/miniterminal/Console.cpp +++ b/src/tests/apps/miniterminal/Console.cpp @@ -17,7 +17,8 @@ #include Console::Console(ViewBuffer *output) - : fOutput(output) + : fState(CONSOLE_STATE_NORMAL), + fOutput(output) { fOutput->GetSize(&fColumns, &fLines); fOutput->SetResizeCallback(&ResizeCallback, this); diff --git a/src/tests/apps/miniterminal/Jamfile b/src/tests/apps/miniterminal/Jamfile index 5932861d71..cd87239e06 100644 --- a/src/tests/apps/miniterminal/Jamfile +++ b/src/tests/apps/miniterminal/Jamfile @@ -4,10 +4,15 @@ UseHeaders [ FDirName $(OBOS_TOP) src tests apps miniterminal ] ; UseHeaders [ FDirName $(OBOS_TOP) src apps terminal MYOB ] ; App MiniTerminal : - MiniApp.cpp - MiniWin.cpp - MiniView.cpp + Arguments.cpp Console.cpp + MiniApp.cpp + MiniView.cpp + MiniWin.cpp ViewBuffer.cpp ; -LinkSharedOSLibs MiniTerminal : libroot.so libbe.so ; +if $(TARGET_PLATFORM) = haiku { + LinkSharedOSLibs MiniTerminal : libroot.so libbe.so ; +} else { + LinkSharedOSLibs MiniTerminal : libroot.so libopenbeos.so ; +} diff --git a/src/tests/apps/miniterminal/MiniApp.cpp b/src/tests/apps/miniterminal/MiniApp.cpp index b0a69f9965..08ce73bad5 100644 --- a/src/tests/apps/miniterminal/MiniApp.cpp +++ b/src/tests/apps/miniterminal/MiniApp.cpp @@ -6,14 +6,16 @@ */ #include -#include "MiniApp.h" -#include "MiniWin.h" -#include "MiniView.h" -MiniApp::MiniApp(BRect bounds) +#include "Arguments.h" +#include "MiniApp.h" +#include "MiniView.h" +#include "MiniWin.h" + +MiniApp::MiniApp(const Arguments &args) : BApplication("application/x-vnd.Haiku.MiniTerminal") { - fWindow = new MiniWin(bounds); + fWindow = new MiniWin(args); fWindow->Show(); } @@ -31,26 +33,12 @@ MiniApp::~MiniApp() int -main(int argc, const char *argv[]) +main(int argc, const char *const argv[]) { - BRect bounds(50, 50, 630, 435); + Arguments args; + args.Parse(argc, argv); - if (argc >= 3) { - BPoint offset; - sscanf(argv[1], "%f", &offset.x); - sscanf(argv[2], "%f", &offset.y); - bounds.OffsetTo(offset); - } - - if (argc >= 5) { - BPoint size; - sscanf(argv[3], "%f", &size.x); - sscanf(argv[4], "%f", &size.y); - bounds.right = bounds.left + size.x; - bounds.bottom = bounds.top + size.y; - } - - MiniApp *app = new MiniApp(bounds); + MiniApp *app = new MiniApp(args); app->Run(); delete app; return 0; diff --git a/src/tests/apps/miniterminal/MiniApp.h b/src/tests/apps/miniterminal/MiniApp.h index 574ea6f14d..3a526c87f7 100644 --- a/src/tests/apps/miniterminal/MiniApp.h +++ b/src/tests/apps/miniterminal/MiniApp.h @@ -3,11 +3,12 @@ #include +class Arguments; class MiniWin; class MiniApp : public BApplication { public: - MiniApp(BRect bounds); + MiniApp(const Arguments &args); virtual ~MiniApp(); virtual void ReadyToRun(); @@ -16,4 +17,4 @@ private: MiniWin *fWindow; }; -#endif \ No newline at end of file +#endif diff --git a/src/tests/apps/miniterminal/MiniView.cpp b/src/tests/apps/miniterminal/MiniView.cpp index 13917faaaf..4070974950 100644 --- a/src/tests/apps/miniterminal/MiniView.cpp +++ b/src/tests/apps/miniterminal/MiniView.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -26,8 +27,9 @@ #include #include -#include "MiniView.h" +#include "Arguments.h" #include "Console.h" +#include "MiniView.h" #include "VTkeymap.h" @@ -65,8 +67,9 @@ Setenv(const char *var, const char *value) environ [++envindex] = NULL; } -MiniView::MiniView(BRect frame) - : ViewBuffer(frame) +MiniView::MiniView(const Arguments &args) + : ViewBuffer(args.Bounds().OffsetToCopy(0, 0)), + fArguments(args) { // we need a message filter so that we get B_TAB keydowns AddFilter(new BMessageFilter(B_KEY_DOWN, &MiniView::MessageFilter)); @@ -92,11 +95,6 @@ MiniView::Start() // we're a session leader setsid(); - // move our stdin and stdout to the console - dup2(fSlaveFD, 0); - dup2(fSlaveFD, 1); - dup2(fSlaveFD, 2); - if (SpawnThreads() != B_OK) TRACE(("error in SpawnThreads\n")); } @@ -269,12 +267,12 @@ MiniView::SpawnThreads() fConsoleWriter = spawn_thread(&MiniView::ConsoleWriter, "console writer", B_URGENT_DISPLAY_PRIORITY, this); if (fConsoleWriter < 0) return B_ERROR; - TRACE(("console writer thread is: %d\n", fConsoleWriter)); + TRACE(("console writer thread is: %ld\n", fConsoleWriter)); fShellExecutor = spawn_thread(&MiniView::ExecuteShell, "shell process", B_URGENT_DISPLAY_PRIORITY, this); if (fShellExecutor < 0) return B_ERROR; - TRACE(("shell process thread is: %d\n", fShellProcess)); + TRACE(("shell executor thread is: %ld\n", fShellExecutor)); resume_thread(fConsoleWriter); resume_thread(fShellExecutor); @@ -305,11 +303,10 @@ MiniView::ExecuteShell(void *arg) MiniView *view = (MiniView *)arg; for (;;) { - const char *argv[3]; - argv[0] = "/bin/sh"; - argv[1] = "--login"; - argv[2] = NULL; - + int argc; + const char *const *argv; + view->fArguments.GetShellArguments(argc, argv); + int saved_stdin = dup(0); int saved_stdout = dup(1); int saved_stderr = dup(2); @@ -318,19 +315,25 @@ MiniView::ExecuteShell(void *arg) dup2(view->fSlaveFD, 1); dup2(view->fSlaveFD, 2); - view->fShellProcess = load_image(2, argv, (const char **)environ); + view->fShellProcess = load_image(argc, (const char **)argv, + (const char **)environ); setpgid(view->fShellProcess, 0); tcsetpgrp(view->fSlaveFD, view->fShellProcess); - status_t return_code; - wait_for_thread(view->fShellProcess, &return_code); - dup2(saved_stdin, 0); dup2(saved_stdout, 1); dup2(saved_stderr, 2); close(saved_stdin); close(saved_stdout); close(saved_stderr); + + status_t return_code; + wait_for_thread(view->fShellProcess, &return_code); + + if (!view->fArguments.StandardShell()) { + view->Window()->PostMessage(B_QUIT_REQUESTED); + break; + } } return B_OK; diff --git a/src/tests/apps/miniterminal/MiniView.h b/src/tests/apps/miniterminal/MiniView.h index 7baa6d9a4b..9d8c6072eb 100644 --- a/src/tests/apps/miniterminal/MiniView.h +++ b/src/tests/apps/miniterminal/MiniView.h @@ -6,9 +6,11 @@ #include "ViewBuffer.h" #include "Console.h" +class Arguments; + class MiniView : public ViewBuffer { public: - MiniView(BRect frame); + MiniView(const Arguments &args); virtual ~MiniView(); void Start(); @@ -23,6 +25,7 @@ static int32 ConsoleWriter(void *arg); static int32 ExecuteShell(void *arg); static filter_result MessageFilter(BMessage *message, BHandler **target, BMessageFilter *filter); + const Arguments &fArguments; Console *fConsole; int fMasterFD; int fSlaveFD; diff --git a/src/tests/apps/miniterminal/MiniWin.cpp b/src/tests/apps/miniterminal/MiniWin.cpp index c6595d1eff..e66e59437f 100644 --- a/src/tests/apps/miniterminal/MiniWin.cpp +++ b/src/tests/apps/miniterminal/MiniWin.cpp @@ -5,13 +5,15 @@ * Distributed under the Haiku License. */ -#include "MiniWin.h" +#include "Arguments.h" #include "MiniView.h" +#include "MiniWin.h" -MiniWin::MiniWin(BRect bounds) - : BWindow(bounds, "MiniTerminal", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE) +MiniWin::MiniWin(const Arguments &args) + : BWindow(args.Bounds(), "MiniTerminal", B_TITLED_WINDOW, + B_QUIT_ON_WINDOW_CLOSE) { - fView = new MiniView(bounds.OffsetToSelf(0, 0)); + fView = new MiniView(args); AddChild(fView); fView->MakeFocus(); } diff --git a/src/tests/apps/miniterminal/MiniWin.h b/src/tests/apps/miniterminal/MiniWin.h index 0718bab74d..4bf5cc36af 100644 --- a/src/tests/apps/miniterminal/MiniWin.h +++ b/src/tests/apps/miniterminal/MiniWin.h @@ -3,11 +3,12 @@ #include +class Arguments; class MiniView; class MiniWin : public BWindow { public: - MiniWin(BRect bounds); + MiniWin(const Arguments &args); virtual ~MiniWin(); MiniView *View();