From 76052376e257188e4867a26369846195661b252f Mon Sep 17 00:00:00 2001 From: Kelvin Schoofs Date: Wed, 6 Oct 2021 19:17:04 +0200 Subject: [PATCH] Initial fix for home detection for csh/tcsh shell (#295) --- CHANGELOG.md | 3 +++ src/connection.ts | 14 ++++++++++---- src/pseudoTerminal.ts | 4 +++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dac993d..7aac3e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ ## Unreleased +### Hotfix +- Fix the issue with failing home detecting for `csh`/`tcsh` shells (#295) + ### Development changes - More improvements in logging, especially regarding async stack tracing - Properly "set boundaries", detect/analyze and log `toPromise`/`catchingPromise` calls diff --git a/src/connection.ts b/src/connection.ts index 94fb405..24ecc48 100644 --- a/src/connection.ts +++ b/src/connection.ts @@ -22,12 +22,12 @@ export interface Connection { } async function tryGetHome(ssh: Client): Promise { - const exec = await toPromise(cb => ssh.exec('echo "::sshfs:home:$(echo ~)\n"', cb)); + const exec = await toPromise(cb => ssh.exec('echo "::sshfs:home:`echo ~`:"', cb)); let home = ''; exec.stdout.on('data', (chunk: any) => home += chunk); await toPromise(cb => exec.on('close', cb)); if (!home) return null; - return home.match(/::sshfs:home:(.*?)\n/)?.[1] || null; + return home.match(/::sshfs:home:(.*?):/)?.[1] || null; } const TMP_PROFILE_SCRIPT = ` @@ -80,8 +80,9 @@ export class ConnectionManager { protected async _createCommandTerminal(client: Client, authority: string, debugLogging: boolean): Promise { const logging = Logging.scope(`CmdTerm(${authority})`); const shell = await toPromise(cb => client.shell({}, cb)); - shell.write('echo ::sshfs:TTY:$(tty)\n'); + shell.write('echo ::sshfs:TTY:`tty`\n'); return new Promise((resolvePath, rejectPath) => { + setTimeout(() => rejectPath(new Error('Timeout fetching command path')), 10e3); const rl = readline.createInterface(shell.stdout); shell.stdout.once('error', rejectPath); shell.once('close', () => rejectPath()); @@ -168,6 +169,7 @@ export class ConnectionManager { home = ''; } } + logging.debug`Home path: ${home}`; // Calculate the environment const environment: EnvironmentVariable[] = mergeEnvironment([], config.environment); // Set up stuff for receiving remote commands @@ -179,8 +181,12 @@ export class ConnectionManager { const cmdPath = await this._createCommandTerminal(client, name, flagRCDV); environment.push({ key: 'KELVIN_SSHFS_CMD_PATH', value: cmdPath }); const sftp = await toPromise(cb => client.sftp(cb)); - await toPromise(cb => sftp.writeFile('/tmp/.Kelvin_sshfs', TMP_PROFILE_SCRIPT, { mode: 0o666 }, cb)); + await toPromise(cb => sftp.writeFile('/tmp/.Kelvin_sshfs', TMP_PROFILE_SCRIPT, { mode: 0o666 }, cb)).catch(e => { + logging.error`Failed to write profile script to /tmp/.Kelvin_sshfs:\n${e}\nDisabling REMOTE_COMMANDS flag`; + actualConfig.flags = ['-REMOTE_COMMANDS', ...(actualConfig.flags || [])]; + }); } + logging.debug`Environment: ${environment}`; // Set up the Connection object let timeoutCounter = 0; const con: Connection = { diff --git a/src/pseudoTerminal.ts b/src/pseudoTerminal.ts index 540d7b8..5fdd613 100644 --- a/src/pseudoTerminal.ts +++ b/src/pseudoTerminal.ts @@ -202,7 +202,9 @@ export async function createTerminal(options: TerminalOptions): Promise(cb => client.exec(joinCommands(commands, separator)!, { pty: pseudoTtyOptions }, cb)); + const cmd = joinCommands(commands, separator)!; + Logging.debug(`Starting shell for ${connection.actualConfig.name}: ${cmd}`); + const channel = await toPromise(cb => client.exec(cmd, { pty: pseudoTtyOptions }, cb)); if (!channel) throw new Error('Could not create remote terminal'); pseudo.channel = channel; channel.on('exit', onDidClose.fire);