提交 ce414a8c 编写于 作者: D Daniel Imms

Implement terminal inheritEnv on remote

Fixes microsoft/vscode-remote-release#823
上级 cefbf36d
......@@ -21,6 +21,7 @@ import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { getSystemShell, detectAvailableShells } from 'vs/workbench/contrib/terminal/node/terminal';
import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
const RENDERER_NO_PROCESS_ID = -1;
......@@ -522,6 +523,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
const envFromConfig = this._apiInspectConfigToPlain(configProvider.getConfiguration('terminal.integrated').inspect<ITerminalEnvironment>(`env.${platformKey}`));
const workspaceFolders = await this._extHostWorkspace.getWorkspaceFolders2();
const variableResolver = workspaceFolders ? new ExtHostVariableResolverService(workspaceFolders, this._extHostDocumentsAndEditors, configProvider) : undefined;
const baseEnv = terminalConfig.get<boolean>('inheritEnv', true) ? process.env as platform.IProcessEnvironment : await getMainProcessParentEnv();
const env = terminalEnvironment.createTerminalEnvironment(
shellLaunchConfig,
lastActiveWorkspace,
......@@ -530,9 +532,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
isWorkspaceShellAllowed,
pkg.version,
terminalConfig.get<boolean>('setLocaleVariables', false),
// Always inherit the environment as we need to be running in a login shell, this may
// change when macOS servers are supported
process.env as platform.IProcessEnvironment
baseEnv
);
// Fork the process and listen for messages
......
......@@ -7,17 +7,16 @@ import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/
import { ITerminalInstance, IWindowsShellHelper, IShellLaunchConfig, ITerminalChildProcess, IS_WORKSPACE_SHELL_ALLOWED_STORAGE_KEY } from 'vs/workbench/contrib/terminal/common/terminal';
import { WindowsShellHelper } from 'vs/workbench/contrib/terminal/node/windowsShellHelper';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProcessEnvironment, isLinux, isMacintosh, isWindows, platform, Platform } from 'vs/base/common/platform';
import { IProcessEnvironment, platform, Platform } from 'vs/base/common/platform';
import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess';
import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal';
import { Terminal as XTermTerminal } from 'xterm';
import { WebLinksAddon as XTermWebLinksAddon } from 'xterm-addon-web-links';
import { SearchAddon as XTermSearchAddon } from 'xterm-addon-search';
import { readFile } from 'vs/base/node/pfs';
import { basename } from 'vs/base/common/path';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { getDefaultShell, getDefaultShellArgs } from 'vs/workbench/contrib/terminal/common/terminalEnvironment';
import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage';
import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment';
let Terminal: typeof XTermTerminal;
let WebLinksAddon: typeof XTermWebLinksAddon;
......@@ -26,8 +25,6 @@ let SearchAddon: typeof XTermSearchAddon;
export class TerminalInstanceService implements ITerminalInstanceService {
public _serviceBrand: any;
private _mainProcessParentEnv: IProcessEnvironment | undefined;
constructor(
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
......@@ -86,72 +83,7 @@ export class TerminalInstanceService implements ITerminalInstanceService {
return Promise.resolve({ shell, args });
}
public async getMainProcessParentEnv(): Promise<IProcessEnvironment> {
if (this._mainProcessParentEnv) {
return this._mainProcessParentEnv;
}
// For Linux use /proc/<pid>/status to get the parent of the main process and then fetch its
// env using /proc/<pid>/environ.
if (isLinux) {
const mainProcessId = process.ppid;
const codeProcessName = basename(process.argv[0]);
let pid: number = 0;
let ppid: number = mainProcessId;
let name: string = codeProcessName;
do {
pid = ppid;
const status = await readFile(`/proc/${pid}/status`, 'utf8');
const splitByLine = status.split('\n');
splitByLine.forEach(line => {
if (line.indexOf('Name:') === 0) {
name = line.replace(/^Name:\s+/, '');
}
if (line.indexOf('PPid:') === 0) {
ppid = parseInt(line.replace(/^PPid:\s+/, ''));
}
});
} while (name === codeProcessName);
const rawEnv = await readFile(`/proc/${pid}/environ`, 'utf8');
const env = {};
rawEnv.split('\0').forEach(e => {
const i = e.indexOf('=');
env[e.substr(0, i)] = e.substr(i + 1);
});
this._mainProcessParentEnv = env;
}
// For macOS we want the "root" environment as shells by default run as login shells. It
// doesn't appear to be possible to get the "root" environment as `ps eww -o command` for
// PID 1 (the parent of the main process when launched from the dock/finder) returns no
// environment, because of this we will fill in the root environment using a whitelist of
// environment variables that we have.
if (isMacintosh) {
this._mainProcessParentEnv = {};
// This list was generated by diffing launching a terminal with {} and the system
// terminal launched from finder.
const rootEnvVars = [
'SHELL',
'SSH_AUTH_SOCK',
'Apple_PubSub_Socket_Render',
'XPC_FLAGS',
'XPC_SERVICE_NAME',
'HOME',
'LOGNAME',
'TMPDIR'
];
rootEnvVars.forEach(k => {
if (process.env[k]) {
this._mainProcessParentEnv![k] = process.env[k]!;
}
});
}
// TODO: Windows should return a fresh environment block, might need native code?
if (isWindows) {
this._mainProcessParentEnv = process.env as IProcessEnvironment;
}
return this._mainProcessParentEnv!;
public getMainProcessParentEnv(): Promise<IProcessEnvironment> {
return getMainProcessParentEnv();
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { readFile } from 'vs/base/node/pfs';
import { basename } from 'vs/base/common/path';
let mainProcessParentEnv: IProcessEnvironment | undefined;
export async function getMainProcessParentEnv(): Promise<IProcessEnvironment> {
if (mainProcessParentEnv) {
return mainProcessParentEnv;
}
// For Linux use /proc/<pid>/status to get the parent of the main process and then fetch its
// env using /proc/<pid>/environ.
if (isLinux) {
const mainProcessId = process.ppid;
const codeProcessName = basename(process.argv[0]);
let pid: number = 0;
let ppid: number = mainProcessId;
let name: string = codeProcessName;
do {
pid = ppid;
const status = await readFile(`/proc/${pid}/status`, 'utf8');
const splitByLine = status.split('\n');
splitByLine.forEach(line => {
if (line.indexOf('Name:') === 0) {
name = line.replace(/^Name:\s+/, '');
}
if (line.indexOf('PPid:') === 0) {
ppid = parseInt(line.replace(/^PPid:\s+/, ''));
}
});
} while (name === codeProcessName);
const rawEnv = await readFile(`/proc/${pid}/environ`, 'utf8');
const env = {};
rawEnv.split('\0').forEach(e => {
const i = e.indexOf('=');
env[e.substr(0, i)] = e.substr(i + 1);
});
mainProcessParentEnv = env;
}
// For macOS we want the "root" environment as shells by default run as login shells. It
// doesn't appear to be possible to get the "root" environment as `ps eww -o command` for
// PID 1 (the parent of the main process when launched from the dock/finder) returns no
// environment, because of this we will fill in the root environment using a whitelist of
// environment variables that we have.
if (isMacintosh) {
mainProcessParentEnv = {};
// This list was generated by diffing launching a terminal with {} and the system
// terminal launched from finder.
const rootEnvVars = [
'SHELL',
'SSH_AUTH_SOCK',
'Apple_PubSub_Socket_Render',
'XPC_FLAGS',
'XPC_SERVICE_NAME',
'HOME',
'LOGNAME',
'TMPDIR'
];
rootEnvVars.forEach(k => {
if (process.env[k]) {
mainProcessParentEnv![k] = process.env[k]!;
}
});
}
// TODO: Windows should return a fresh environment block, might need native code?
if (isWindows) {
mainProcessParentEnv = process.env as IProcessEnvironment;
}
return mainProcessParentEnv!;
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册