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.
This commit is contained in:
Augustin Cavalier
2025-07-15 17:32:07 -04:00
parent 38e619c671
commit bdda979744
6 changed files with 30 additions and 44 deletions
+3 -4
View File
@@ -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];
+7 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2018, Haiku, Inc. All rights reserved.
* Copyright 2005-2025, Haiku, Inc. All rights reserved.
* Copyright 2005, Ingo Weinhold, <[email protected]>
*
* Distributed under the terms of the MIT License.
@@ -8,12 +8,12 @@
* Jeremiah Bailey, <[email protected]>
* Ingo Weinhold, <[email protected]>
*/
#ifndef ARGUMENTS_H
#define ARGUMENTS_H
#include <Rect.h>
#include <String.h>
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;
};
+2 -14
View File
@@ -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 (...) {
-3
View File
@@ -55,9 +55,6 @@ private:
private:
thread_id fChildCleanupThread;
bool fTerminating;
bool fStartFullscreen;
BString fWindowTitle;
BString fWorkingDirectory;
BWindow* fTermWindow;
Arguments* fArgs;
+16 -13
View File
@@ -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;
+2 -3
View File
@@ -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);