cac07c1472
- Distinguish just-an-int from seconds all across the API
181 lines
6.0 KiB
C++
181 lines
6.0 KiB
C++
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
|
*
|
|
* Copyright 2018, Adriaan de Groot <groot@kde.org>
|
|
*
|
|
* Calamares is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Calamares is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "CommandList.h"
|
|
|
|
#include "GlobalStorage.h"
|
|
#include "JobQueue.h"
|
|
|
|
// #include "utils/CalamaresUtils.h"
|
|
#include "utils/CalamaresUtilsSystem.h"
|
|
#include "utils/Logger.h"
|
|
#include "utils/Variant.h"
|
|
|
|
#include <QCoreApplication>
|
|
#include <QVariantList>
|
|
|
|
namespace CalamaresUtils
|
|
{
|
|
|
|
static CommandLine get_variant_object( const QVariantMap& m )
|
|
{
|
|
QString command = CalamaresUtils::getString( m, "command" );
|
|
int timeout = CalamaresUtils::getInteger( m, "timeout", -1 );
|
|
|
|
if ( !command.isEmpty() )
|
|
return CommandLine( command, timeout >= 0 ? std::chrono::seconds( timeout ) : CommandLine::TimeoutNotSet() );
|
|
cWarning() << "Bad CommandLine element" << m;
|
|
return CommandLine();
|
|
}
|
|
|
|
static CommandList_t get_variant_stringlist( const QVariantList& l )
|
|
{
|
|
CommandList_t retl;
|
|
unsigned int count = 0;
|
|
for ( const auto& v : l )
|
|
{
|
|
if ( v.type() == QVariant::String )
|
|
retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet() ) );
|
|
else if ( v.type() == QVariant::Map )
|
|
{
|
|
auto command( get_variant_object( v.toMap() ) );
|
|
if ( command.isValid() )
|
|
retl.append( command );
|
|
// Otherwise warning is already given
|
|
}
|
|
else
|
|
cWarning() << "Bad CommandList element" << count << v.type() << v;
|
|
++count;
|
|
}
|
|
return retl;
|
|
}
|
|
|
|
CommandList::CommandList( bool doChroot, std::chrono::seconds timeout )
|
|
: m_doChroot( doChroot )
|
|
, m_timeout( timeout )
|
|
{
|
|
}
|
|
|
|
CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, std::chrono::seconds timeout )
|
|
: CommandList( doChroot, timeout )
|
|
{
|
|
if ( v.type() == QVariant::List )
|
|
{
|
|
const auto v_list = v.toList();
|
|
if ( v_list.count() )
|
|
append( get_variant_stringlist( v_list ) );
|
|
else
|
|
cWarning() << "Empty CommandList";
|
|
}
|
|
else if ( v.type() == QVariant::String )
|
|
append( v.toString() );
|
|
else if ( v.type() == QVariant::Map )
|
|
{
|
|
auto c( get_variant_object( v.toMap() ) );
|
|
if ( c.isValid() )
|
|
append( c );
|
|
// Otherwise warning is already given
|
|
}
|
|
else
|
|
cWarning() << "CommandList does not understand variant" << v.type();
|
|
}
|
|
|
|
CommandList::~CommandList()
|
|
{
|
|
}
|
|
|
|
static inline bool
|
|
findInCommands( const CommandList& l, const QString& needle )
|
|
{
|
|
for ( CommandList::const_iterator i = l.cbegin(); i != l.cend(); ++i )
|
|
if ( i->command().contains( needle ) )
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
Calamares::JobResult CommandList::run()
|
|
{
|
|
QLatin1Literal rootMagic( "@@ROOT@@" );
|
|
QLatin1Literal userMagic( "@@USER@@" );
|
|
|
|
System::RunLocation location = m_doChroot ? System::RunLocation::RunInTarget : System::RunLocation::RunInHost;
|
|
|
|
/* Figure out the replacement for @@ROOT@@ */
|
|
QString root = QStringLiteral( "/" );
|
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
|
|
|
bool needsRootSubstitution = findInCommands( *this, rootMagic );
|
|
if ( needsRootSubstitution && ( location == System::RunLocation::RunInHost ) )
|
|
{
|
|
if ( !gs || !gs->contains( "rootMountPoint" ) )
|
|
{
|
|
cError() << "No rootMountPoint defined.";
|
|
return Calamares::JobResult::error( QCoreApplication::translate( "CommandList", "Could not run command." ),
|
|
QCoreApplication::translate( "CommandList", "The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined." ) );
|
|
}
|
|
root = gs->value( "rootMountPoint" ).toString();
|
|
}
|
|
|
|
bool needsUserSubstitution = findInCommands( *this, userMagic );
|
|
if ( needsUserSubstitution && ( !gs || !gs->contains( "username" ) ) )
|
|
{
|
|
cError() << "No username defined.";
|
|
return Calamares::JobResult::error(
|
|
QCoreApplication::translate( "CommandList", "Could not run command." ),
|
|
QCoreApplication::translate( "CommandList", "The command needs to know the user's name, but no username is defined." ) );
|
|
}
|
|
QString user = gs->value( "username" ).toString(); // may be blank if unset
|
|
|
|
for ( CommandList::const_iterator i = cbegin(); i != cend(); ++i )
|
|
{
|
|
QString processed_cmd = i->command();
|
|
processed_cmd.replace( rootMagic, root ).replace( userMagic, user );
|
|
bool suppress_result = false;
|
|
if ( processed_cmd.startsWith( '-' ) )
|
|
{
|
|
suppress_result = true;
|
|
processed_cmd.remove( 0, 1 ); // Drop the -
|
|
}
|
|
|
|
QStringList shell_cmd { "/bin/sh", "-c" };
|
|
shell_cmd << processed_cmd;
|
|
|
|
std::chrono::seconds timeout = i->timeout() >= std::chrono::seconds::zero() ? i->timeout() : m_timeout;
|
|
ProcessResult r = System::runCommand(
|
|
location, shell_cmd, QString(), QString(), timeout );
|
|
|
|
if ( r.getExitCode() != 0 )
|
|
{
|
|
if ( suppress_result )
|
|
cDebug() << "Error code" << r.getExitCode() << "ignored by CommandList configuration.";
|
|
else
|
|
return r.explainProcess( processed_cmd, timeout );
|
|
}
|
|
}
|
|
|
|
return Calamares::JobResult::ok();
|
|
}
|
|
|
|
void
|
|
CommandList::append( const QString& s )
|
|
{
|
|
append( CommandLine( s, m_timeout ) );
|
|
}
|
|
|
|
} // namespace
|