Skip to content

Commit

Permalink
child-process: fix switches for alternative shells on Windows
Browse files Browse the repository at this point in the history
On Windows, normalizeSpawnArguments set "/d /s /c" for any shells.
It cause exec and other methods are limited to cmd.exe as a shell.

Powershell and git-bash are often used instead of cmd.exe,
and they can recieve "-c" switch like unix shells.
So normalizeSpawnArguments is changed to set "/d /s /c" for cmd.exe,
and "-c" for others.

Fixes: nodejs#21905
  • Loading branch information
tkamenoko committed Jul 26, 2018
1 parent 36a15a1 commit 9c9fe57
Showing 1 changed file with 29 additions and 24 deletions.
53 changes: 29 additions & 24 deletions lib/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ function normalizeExecArgs(command, options, callback) {
exports.exec = function exec(command /* , options, callback */) {
var opts = normalizeExecArgs.apply(null, arguments);
return exports.execFile(opts.file,
opts.options,
opts.callback);
opts.options,
opts.callback);
};

const customPromiseExecFunction = (orig) => {
Expand Down Expand Up @@ -381,7 +381,7 @@ const _deprecatedCustomFds = deprecate(
return fd === -1 ? 'pipe' : fd;
});
}, 'child_process: options.customFds option is deprecated. ' +
'Use options.stdio instead.', 'DEP0006');
'Use options.stdio instead.', 'DEP0006');

function _convertCustomFds(options) {
if (options.customFds && !options.stdio) {
Expand All @@ -399,7 +399,7 @@ function normalizeSpawnArguments(file, args, options) {
if (Array.isArray(args)) {
args = args.slice(0);
} else if (args !== undefined &&
(args === null || typeof args !== 'object')) {
(args === null || typeof args !== 'object')) {
throw new ERR_INVALID_ARG_TYPE('args', 'object', args);
} else {
options = args;
Expand All @@ -413,15 +413,15 @@ function normalizeSpawnArguments(file, args, options) {

// Validate the cwd, if present.
if (options.cwd != null &&
typeof options.cwd !== 'string') {
typeof options.cwd !== 'string') {
throw new ERR_INVALID_ARG_TYPE('options.cwd', 'string', options.cwd);
}

// Validate detached, if present.
if (options.detached != null &&
typeof options.detached !== 'boolean') {
typeof options.detached !== 'boolean') {
throw new ERR_INVALID_ARG_TYPE('options.detached',
'boolean', options.detached);
'boolean', options.detached);
}

// Validate the uid, if present.
Expand All @@ -436,45 +436,50 @@ function normalizeSpawnArguments(file, args, options) {

// Validate the shell, if present.
if (options.shell != null &&
typeof options.shell !== 'boolean' &&
typeof options.shell !== 'string') {
typeof options.shell !== 'boolean' &&
typeof options.shell !== 'string') {
throw new ERR_INVALID_ARG_TYPE('options.shell',
['boolean', 'string'], options.shell);
['boolean', 'string'], options.shell);
}

// Validate argv0, if present.
if (options.argv0 != null &&
typeof options.argv0 !== 'string') {
typeof options.argv0 !== 'string') {
throw new ERR_INVALID_ARG_TYPE('options.argv0', 'string', options.argv0);
}

// Validate windowsHide, if present.
if (options.windowsHide != null &&
typeof options.windowsHide !== 'boolean') {
typeof options.windowsHide !== 'boolean') {
throw new ERR_INVALID_ARG_TYPE('options.windowsHide',
'boolean', options.windowsHide);
'boolean', options.windowsHide);
}

// Validate windowsVerbatimArguments, if present.
if (options.windowsVerbatimArguments != null &&
typeof options.windowsVerbatimArguments !== 'boolean') {
typeof options.windowsVerbatimArguments !== 'boolean') {
throw new ERR_INVALID_ARG_TYPE('options.windowsVerbatimArguments',
'boolean',
options.windowsVerbatimArguments);
'boolean',
options.windowsVerbatimArguments);
}

// Make a shallow copy so we don't clobber the user's options object.
options = Object.assign({}, options);

if (options.shell) {
const command = [file].concat(args).join(' ');

// Set the shell, switches, and commands.
if (process.platform === 'win32') {
if (typeof options.shell === 'string')
file = options.shell;
else
file = process.env.comspec || 'cmd.exe';
args = ['/d', '/s', '/c', `"${command}"`];
// "/d /s /c" is used only for cmd.exe.
if (file.endsWith("cmd.exe") || file.endsWith("cmd")) {
args = ['/d', '/s', '/c', `"${command}"`];
} else {
args = ['-c', `"${command}"`];
}
options.windowsVerbatimArguments = true;
} else {
if (typeof options.shell === 'string')
Expand Down Expand Up @@ -578,8 +583,8 @@ function spawnSync(/* file, args, options */) {
pipe.input = Buffer.from(input, options.encoding);
} else {
throw new ERR_INVALID_ARG_TYPE(`options.stdio[${i}]`,
['Buffer', 'Uint8Array', 'string'],
input);
['Buffer', 'Uint8Array', 'string'],
input);
}
}
}
Expand Down Expand Up @@ -656,8 +661,8 @@ function validateTimeout(timeout) {
function validateMaxBuffer(maxBuffer) {
if (maxBuffer != null && !(typeof maxBuffer === 'number' && maxBuffer >= 0)) {
throw new ERR_OUT_OF_RANGE('options.maxBuffer',
'a positive number',
maxBuffer);
'a positive number',
maxBuffer);
}
}

Expand All @@ -667,7 +672,7 @@ function sanitizeKillSignal(killSignal) {
return convertToValidSignal(killSignal);
} else if (killSignal != null) {
throw new ERR_INVALID_ARG_TYPE('options.killSignal',
['string', 'number'],
killSignal);
['string', 'number'],
killSignal);
}
}

0 comments on commit 9c9fe57

Please sign in to comment.