//
// Copyright (c) 2010-2018 Antmicro
// Copyright (c) 2011-2015 Realtime Embedded
//
// This file is licensed under the MIT License.
// Full license text is available in 'licenses/MIT.txt'.
//
using System;
using System.Diagnostics;
namespace Antmicro.Renode.Utilities
{
///
/// Sudo tools. Set of methods related to the process elevation.
///
public static class SudoTools
{
///
/// Wraps the command into a sudo-tool call if necessary, creates a new Process object and exectues it.
///
///
/// Checks whether user is root. If it is exectues command, id not tries to elevate priviledged and run the command.
///
/// The sudo execute.
/// Command.
/// Command's arguments.
/// Optional description.
public static Process EnsureSudoExecute(string command, string arguments = "", string description = "")
{
Process process;
process = Misc.IsRoot ? Process.Start(command, arguments) : SudoExecute(command + " " + arguments, description);
return process;
}
///
/// Tries to wrap existing Process, with supported sudo tool. It switched the command's filename and arguments, and wraps them
/// into a call to the supported sudo tool, if it's found.
///
/// Process to be elevated.
/// Process description.
public static void EnsureSudoProcess(Process process, string description = "")
{
if(Misc.IsRoot)
{
return;
}
Process sudoProcess = process;
string sudoName = FindSudoToolName();
if(string.IsNullOrWhiteSpace(sudoProcess.StartInfo.FileName))
{
throw new ArgumentException("EnsureSudoProcess needs to work on a process with initliazed StartInfo.FileName.");
}
var command = sudoProcess.StartInfo.FileName + " " + sudoProcess.StartInfo.Arguments;
sudoProcess.StartInfo.Arguments = SudoDecorateCommand(sudoName, command, description);
sudoProcess.StartInfo.FileName = sudoName;
}
///
/// Finds the name of the sudo tool.
///
/// true, if sudo tool name was found, false otherwise.
/// Sudo tool name, if found.
private static bool TryFindSudoToolName(out string name)
{
name = default(string);
foreach(var nameToCheck in knownToolNames)
{
if(Misc.IsCommandAvaialble(nameToCheck))
{
name = nameToCheck;
return true;
}
}
return false;
}
///
/// Finds the name of the sudo tool. Throwing version of .
///
/// The sudo tool name.
private static string FindSudoToolName()
{
string name;
if(!TryFindSudoToolName(out name))
{
throw new PlatformNotSupportedException(
String.Format("Error: No supported sudo tool found. Supported tools are {0}.", string.Join(", ", knownToolNames))
);
}
return name;
}
///
/// Tries to find sudo tool, and execute the command with elevated rigths.
///
/// The Process object, after the execution.
/// Command.
/// Description.
private static Process SudoExecute(string command, string description = "")
{
string sudoName = FindSudoToolName();
Process process;
command = SudoDecorateCommand(sudoName, command, description);
process = Process.Start(sudoName, command);
return process;
}
///
/// Decorates the command for a specific sudo tool.
///
/// The decorated command.
/// Sudo tool name.
/// Command to be decorated.
/// Description.
private static string SudoDecorateCommand(string sudoName, string command, string description = "")
{
string result;
switch(sudoName)
{
// Tool specific adjustments.
case "gksudo":
result = string.Format(@"-D ""{0}"" ""{1}""", description, command);
break;
case "kdesudo":
result = string.Format(@"-c ""{0}"" --comment ""{1}""", command, description);
break;
case "pkexec":
// We do nothing, because 'pkexec' (version 0.105) doesn't accept description as a parameter.
default:
result = command;
break;
}
return result;
}
///
/// List of supported tool names.
///
private static string[] knownToolNames = { "gksudo", "kdesudo", "pkexec" };
}
}