From bdda9797444f728d9c55dce42d0ac59c47f5b159 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Tue, 15 Jul 2025 17:32:07 -0400 Subject: [PATCH] Terminal: Don't chdir() but pass the working directory down to _Spawn(). If we change our current directory, it will be retained as a reference down inside the VFS, preventing filesystems from being unmounted, among other things. Fixes #19684. --- src/apps/terminal/Arguments.cpp | 7 +++---- src/apps/terminal/Arguments.h | 14 +++++++------- src/apps/terminal/TermApp.cpp | 16 ++-------------- src/apps/terminal/TermApp.h | 3 --- src/apps/terminal/TermWindow.cpp | 29 ++++++++++++++++------------- src/apps/terminal/TermWindow.h | 5 ++--- 6 files changed, 30 insertions(+), 44 deletions(-) diff --git a/src/apps/terminal/Arguments.cpp b/src/apps/terminal/Arguments.cpp index 338513b2bc..833b4af037 100644 --- a/src/apps/terminal/Arguments.cpp +++ b/src/apps/terminal/Arguments.cpp @@ -47,8 +47,7 @@ Arguments::~Arguments() void Arguments::Parse(int argc, const char* const* argv) { - int argi; - for (argi = 1; argi < argc; argi ++) { + for (int argi = 1; argi < argc; argi++) { const char* arg = argv[argi]; if (*arg == '-') { @@ -56,13 +55,13 @@ Arguments::Parse(int argc, const char* const* argv) fUsageRequested = true; else if (strcmp(arg, "-t") == 0 || strcmp(arg, "--title") == 0) { // title - if (argi >= argc) + if ((argi + 1) >= argc) fUsageRequested = true; else fTitle = argv[++argi]; } else if (strcmp(arg, "-w") == 0 || strcmp(arg, "--working-directory") == 0) { - if (argi >= argc) + if ((argi + 1) >= argc) fUsageRequested = true; else fWorkingDirectory = argv[++argi]; diff --git a/src/apps/terminal/Arguments.h b/src/apps/terminal/Arguments.h index 98c243c94d..7e580cf525 100644 --- a/src/apps/terminal/Arguments.h +++ b/src/apps/terminal/Arguments.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2018, Haiku, Inc. All rights reserved. + * Copyright 2005-2025, Haiku, Inc. All rights reserved. * Copyright 2005, Ingo Weinhold, * * Distributed under the terms of the MIT License. @@ -8,12 +8,12 @@ * Jeremiah Bailey, * Ingo Weinhold, */ - - #ifndef ARGUMENTS_H #define ARGUMENTS_H + #include +#include class Arguments { public: @@ -23,8 +23,8 @@ public: void Parse(int argc, const char* const* argv); BRect Bounds() const { return fBounds; } - const char* Title() const { return fTitle; } - const char* WorkingDir() const { return fWorkingDirectory; } + BString Title() const { return fTitle; } + BString WorkingDir() const { return fWorkingDirectory; } bool StandardShell() const { return fStandardShell; } bool FullScreen() const { return fFullScreen; } bool UsageRequested() const { return fUsageRequested; } @@ -39,8 +39,8 @@ private: bool fFullScreen; int fShellArgumentCount; const char** fShellArguments; - const char* fTitle; - const char* fWorkingDirectory; + BString fTitle; + BString fWorkingDirectory; }; diff --git a/src/apps/terminal/TermApp.cpp b/src/apps/terminal/TermApp.cpp index a73df789a2..f8fc73767a 100644 --- a/src/apps/terminal/TermApp.cpp +++ b/src/apps/terminal/TermApp.cpp @@ -62,7 +62,6 @@ TermApp::TermApp() BApplication(TERM_SIGNATURE), fChildCleanupThread(-1), fTerminating(false), - fStartFullscreen(false), fTermWindow(NULL), fArgs(NULL) { @@ -137,7 +136,7 @@ TermApp::ReadyToRun() } // using BScreen::Frame isn't enough - if (fStartFullscreen) + if (fArgs->FullScreen()) BMessenger(fTermWindow).SendMessage(FULLSCREEN); } @@ -205,16 +204,6 @@ TermApp::ArgvReceived(int32 argc, char **argv) PostMessage(B_QUIT_REQUESTED); return; } - - if (fArgs->Title() != NULL) - fWindowTitle = fArgs->Title(); - - if (fArgs->WorkingDir() != NULL) { - fWorkingDirectory = fArgs->WorkingDir(); - chdir(fWorkingDirectory); - } - - fStartFullscreen = fArgs->FullScreen(); } @@ -239,7 +228,6 @@ TermApp::RefsReceived(BMessage* message) // if App opened by Pref file if (strcmp(mimetype, PREFFILE_MIMETYPE) == 0) { - BEntry ent(&ref); BPath path(&ent); PrefHandler::Default()->OpenText(path.Path()); @@ -259,7 +247,7 @@ status_t TermApp::_MakeTermWindow() { try { - fTermWindow = new TermWindow(fWindowTitle, fArgs); + fTermWindow = new TermWindow(*fArgs); } catch (int error) { return (status_t)error; } catch (...) { diff --git a/src/apps/terminal/TermApp.h b/src/apps/terminal/TermApp.h index 460f4c488d..96cb769549 100644 --- a/src/apps/terminal/TermApp.h +++ b/src/apps/terminal/TermApp.h @@ -55,9 +55,6 @@ private: private: thread_id fChildCleanupThread; bool fTerminating; - bool fStartFullscreen; - BString fWindowTitle; - BString fWorkingDirectory; BWindow* fTermWindow; Arguments* fArgs; diff --git a/src/apps/terminal/TermWindow.cpp b/src/apps/terminal/TermWindow.cpp index fc8852ab30..09cb99cfa5 100644 --- a/src/apps/terminal/TermWindow.cpp +++ b/src/apps/terminal/TermWindow.cpp @@ -181,9 +181,9 @@ struct TermWindow::Session { // #pragma mark - TermWindow -TermWindow::TermWindow(const BString& title, Arguments* args) +TermWindow::TermWindow(const Arguments& args) : - BWindow(BRect(0, 0, 0, 0), title, B_DOCUMENT_WINDOW, + BWindow(BRect(0, 0, 0, 0), args.Title(), B_DOCUMENT_WINDOW, B_CURRENT_WORKSPACE | B_QUIT_ON_WINDOW_CLOSE), fTitleUpdateRunner(this, BMessage(kUpdateTitles), 1000000), fNextSessionID(0), @@ -216,7 +216,7 @@ TermWindow::TermWindow(const BString& title, Arguments* args) get_key_map(&fKeymap, &fKeymapChars); // apply the title settings - fTitle.pattern = title; + fTitle.pattern = args.Title(); if (fTitle.pattern.Length() == 0) { fTitle.pattern = B_TRANSLATE_SYSTEM_NAME("Terminal"); @@ -228,7 +228,7 @@ TermWindow::TermWindow(const BString& title, Arguments* args) fTitle.patternUserDefined = true; fTitle.title = fTitle.pattern; - fTitle.pattern = title; + fTitle.pattern = args.Title(); _TitleSettingsChanged(); @@ -259,7 +259,7 @@ TermWindow::TermWindow(const BString& title, Arguments* args) // init the GUI and add a tab _InitWindow(); - _AddTab(args); + _AddTab(&args, args.WorkingDir()); // Announce our window as no longer minimized. That's not true, since it's // still hidden at this point, but it will be shown very soon. @@ -749,19 +749,22 @@ TermWindow::MessageReceived(BMessage *message) { // Set our current working directory to that of the active tab, so // that the new terminal and its shell inherit it. - // Note: That's a bit lame. We should rather fork() and change the - // CWD in the child, but since ATM there aren't any side effects of - // changing our CWD, we save ourselves the trouble. + const char* argv[] = {NULL, NULL, NULL}; + int32 argc = 0; + ActiveProcessInfo activeProcessInfo; - if (_ActiveTermView()->GetActiveProcessInfo(activeProcessInfo)) - chdir(activeProcessInfo.CurrentDirectory()); + if (_ActiveTermView()->GetActiveProcessInfo(activeProcessInfo)) { + argv[0] = "-w"; + argv[1] = activeProcessInfo.CurrentDirectory(); + argc = 2; + } app_info info; be_app->GetAppInfo(&info); // try launching two different ways to work around possible problems - if (be_roster->Launch(&info.ref) != B_OK) - be_roster->Launch(TERM_SIGNATURE); + if (be_roster->Launch(&info.ref, argc, argv) != B_OK) + be_roster->Launch(TERM_SIGNATURE, argc, argv); break; } @@ -1341,7 +1344,7 @@ TermWindow::_NewTab() void -TermWindow::_AddTab(Arguments* args, const BString& currentDirectory) +TermWindow::_AddTab(const Arguments* args, const BString& currentDirectory) { int argc = 0; const char* const* argv = NULL; diff --git a/src/apps/terminal/TermWindow.h b/src/apps/terminal/TermWindow.h index 5ec3505e4d..244a6ae7c1 100644 --- a/src/apps/terminal/TermWindow.h +++ b/src/apps/terminal/TermWindow.h @@ -58,8 +58,7 @@ class TermWindow : public BWindow, private SmartTabView::Listener, private TermView::Listener, private SetTitleDialog::Listener, private TerminalRoster::Listener { public: - TermWindow(const BString& title, - Arguments* args); + TermWindow(const Arguments& args); virtual ~TermWindow(); void SessionChanged(); @@ -154,7 +153,7 @@ private: void _DoPrint(); void _NewTab(); - void _AddTab(Arguments* args, + void _AddTab(const Arguments* args, const BString& currentDirectory = BString()); void _RemoveTab(int32 index);