Improve Linux support to match macOS and Windows
Preserve current working directory. Support explicit options.env environment variables. Support multiple commands separated by semicolons. Distinguish between elevation errors and command errors. Fixes: #39 Fixes: #88 Fixes: #91
This commit is contained in:
parent
ab3a0bd981
commit
7e2db9e19e
1 changed files with 40 additions and 5 deletions
45
index.js
45
index.js
|
@ -130,6 +130,13 @@ function Linux(instance, end) {
|
||||||
function(error, binary) {
|
function(error, binary) {
|
||||||
if (error) return end(error);
|
if (error) return end(error);
|
||||||
var command = [];
|
var command = [];
|
||||||
|
// Preserve current working directory:
|
||||||
|
command.push('cd "' + EscapeDoubleQuotes(Node.process.cwd()) + '";');
|
||||||
|
// Export environment variables:
|
||||||
|
for (var key in instance.options.env) {
|
||||||
|
var value = instance.options.env[key];
|
||||||
|
command.push('export ' + key + '="' + EscapeDoubleQuotes(value) + '";');
|
||||||
|
}
|
||||||
command.push('"' + EscapeDoubleQuotes(binary) + '"');
|
command.push('"' + EscapeDoubleQuotes(binary) + '"');
|
||||||
if (/kdesudo/i.test(binary)) {
|
if (/kdesudo/i.test(binary)) {
|
||||||
command.push(
|
command.push(
|
||||||
|
@ -142,15 +149,43 @@ function Linux(instance, end) {
|
||||||
} else if (/pkexec/i.test(binary)) {
|
} else if (/pkexec/i.test(binary)) {
|
||||||
command.push('--disable-internal-agent');
|
command.push('--disable-internal-agent');
|
||||||
}
|
}
|
||||||
command.push(instance.command);
|
var magic = 'SUDOPROMPT\n';
|
||||||
|
command.push(
|
||||||
|
'/bin/bash -c "echo ' + EscapeDoubleQuotes(magic.trim()) + '; ' +
|
||||||
|
EscapeDoubleQuotes(instance.command) +
|
||||||
|
'"'
|
||||||
|
);
|
||||||
command = command.join(' ');
|
command = command.join(' ');
|
||||||
Node.child.exec(command, { maxBuffer: MAX_BUFFER },
|
Node.child.exec(command, { maxBuffer: MAX_BUFFER },
|
||||||
function(error, stdout, stderr) {
|
function(error, stdout, stderr) {
|
||||||
if (error) {
|
// ISSUE 88:
|
||||||
|
// We must distinguish between elevation errors and command errors.
|
||||||
|
//
|
||||||
|
// KDESUDO:
|
||||||
|
// kdesudo provides no way to do this. We add a magic marker to know
|
||||||
|
// if elevation succeeded. Any error thereafter is a command error.
|
||||||
|
//
|
||||||
|
// PKEXEC:
|
||||||
|
// "Upon successful completion, the return value is the return value of
|
||||||
|
// PROGRAM. If the calling process is not authorized or an
|
||||||
|
// authorization could not be obtained through authentication or an
|
||||||
|
// error occured, pkexec exits with a return value of 127. If the
|
||||||
|
// authorization could not be obtained because the user dismissed the
|
||||||
|
// authentication dialog, pkexec exits with a return value of 126."
|
||||||
|
//
|
||||||
|
// However, we do not rely on pkexec's return of 127 since our magic
|
||||||
|
// marker is more reliable, and we already use it for kdesudo.
|
||||||
|
var elevated = stdout ? stdout.toString('utf8', 0, magic.length) : '';
|
||||||
|
if (elevated) stdout = stdout.slice(magic.length);
|
||||||
|
// Only normalize the error if it is definitely not a command error:
|
||||||
|
// In other words, if we know that the command was never elevated.
|
||||||
|
// We do not inspect error messages beyond NO_POLKIT_AGENT.
|
||||||
|
// We cannot rely on English errors because of internationalization.
|
||||||
|
if (error && !elevated) {
|
||||||
if (/No authentication agent found/.test(stderr)) {
|
if (/No authentication agent found/.test(stderr)) {
|
||||||
error = new Error(NO_POLKIT_AGENT);
|
error.message = NO_POLKIT_AGENT;
|
||||||
} else if (/Request dismissed|Command failed/i.test(error)) {
|
} else {
|
||||||
error = new Error(PERMISSION_DENIED);
|
error.message = PERMISSION_DENIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
end(error, stdout, stderr);
|
end(error, stdout, stderr);
|
||||||
|
|
Loading…
Reference in a new issue