diff --git a/src/vs/base/node/shell.ts b/src/vs/base/node/shell.ts new file mode 100644 index 00000000000..0ae5fe92ac6 --- /dev/null +++ b/src/vs/base/node/shell.ts @@ -0,0 +1,70 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as os from 'os'; +import * as platform from 'vs/base/common/platform'; +import * as processes from 'vs/base/node/processes'; + +/** + * Gets the detected default shell for the _system_, not to be confused with VS Code's _default_ + * shell that the terminal uses by default. + * @param p The platform to detect the shell of. + */ +export function getSystemShell(p: platform.Platform, environment: platform.IProcessEnvironment = process.env as platform.IProcessEnvironment): string { + if (p === platform.Platform.Windows) { + if (platform.isWindows) { + return getSystemShellWindows(environment); + } + // Don't detect Windows shell when not on Windows + return processes.getWindowsShell(environment); + } + // Only use $SHELL for the current OS + if (platform.isLinux && p === platform.Platform.Mac || platform.isMacintosh && p === platform.Platform.Linux) { + return '/bin/bash'; + } + return getSystemShellUnixLike(environment); +} + +let _TERMINAL_DEFAULT_SHELL_UNIX_LIKE: string | null = null; +function getSystemShellUnixLike(environment: platform.IProcessEnvironment): string { + if (!_TERMINAL_DEFAULT_SHELL_UNIX_LIKE) { + let unixLikeTerminal: string; + if (platform.isWindows) { + unixLikeTerminal = '/bin/bash'; // for WSL + } else { + unixLikeTerminal = environment.SHELL; + + if (!unixLikeTerminal) { + try { + // It's possible for $SHELL to be unset, this API reads /etc/passwd. See https://github.com/github/codespaces/issues/1639 + // Node docs: "Throws a SystemError if a user has no username or homedir." + unixLikeTerminal = os.userInfo().shell; + } catch (err) { } + } + + if (!unixLikeTerminal) { + unixLikeTerminal = 'sh'; + } + + // Some systems have $SHELL set to /bin/false which breaks the terminal + if (unixLikeTerminal === '/bin/false') { + unixLikeTerminal = '/bin/bash'; + } + } + _TERMINAL_DEFAULT_SHELL_UNIX_LIKE = unixLikeTerminal; + } + return _TERMINAL_DEFAULT_SHELL_UNIX_LIKE; +} + +let _TERMINAL_DEFAULT_SHELL_WINDOWS: string | null = null; +function getSystemShellWindows(environment: platform.IProcessEnvironment): string { + if (!_TERMINAL_DEFAULT_SHELL_WINDOWS) { + const isAtLeastWindows10 = platform.isWindows && parseFloat(os.release()) >= 10; + const is32ProcessOn64Windows = environment.hasOwnProperty('PROCESSOR_ARCHITEW6432'); + const powerShellPath = `${environment.windir}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`; + _TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell(environment); + } + return _TERMINAL_DEFAULT_SHELL_WINDOWS; +} diff --git a/src/vs/code/node/shellEnv.ts b/src/vs/code/node/shellEnv.ts index 29ef8c143b3..2ea93f9c5af 100644 --- a/src/vs/code/node/shellEnv.ts +++ b/src/vs/code/node/shellEnv.ts @@ -5,11 +5,12 @@ import { spawn } from 'child_process'; import { generateUuid } from 'vs/base/common/uuid'; -import { isWindows } from 'vs/base/common/platform'; +import { isWindows, platform } from 'vs/base/common/platform'; import { ILogService } from 'vs/platform/log/common/log'; import { NativeParsedArgs } from 'vs/platform/environment/common/argv'; import { isLaunchedFromCli } from 'vs/platform/environment/node/argvHelper'; import { toErrorMessage } from 'vs/base/common/errorMessage'; +import { getSystemShell } from 'vs/base/node/shell'; /** * We need to get the environment from a user's shell. @@ -78,7 +79,8 @@ async function doResolveUnixShellEnv(logService: ILogService): Promise= 10; - const is32ProcessOn64Windows = environment.hasOwnProperty('PROCESSOR_ARCHITEW6432'); - const powerShellPath = `${environment.windir}\\${is32ProcessOn64Windows ? 'Sysnative' : 'System32'}\\WindowsPowerShell\\v1.0\\powershell.exe`; - _TERMINAL_DEFAULT_SHELL_WINDOWS = isAtLeastWindows10 ? powerShellPath : processes.getWindowsShell(environment); - } - return _TERMINAL_DEFAULT_SHELL_WINDOWS; -} - let detectedDistro = LinuxDistro.Unknown; if (platform.isLinux) { const file = '/etc/os-release';