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();