2018-01-15 11:59:44 +01:00
/* === 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"
2018-01-29 21:08:42 +01:00
# include "utils/CalamaresUtils.h"
2018-01-15 11:59:44 +01:00
# include "utils/CalamaresUtilsSystem.h"
# include "utils/Logger.h"
2018-02-07 17:03:55 +01:00
# include <QCoreApplication>
2018-01-15 11:59:44 +01:00
# include <QVariantList>
2018-01-29 17:01:28 +01:00
namespace CalamaresUtils
{
2018-01-29 21:08:42 +01:00
static CommandLine get_variant_object ( const QVariantMap & m )
{
QString command = CalamaresUtils : : getString ( m , " command " ) ;
2018-01-29 21:25:18 +01:00
int timeout = CalamaresUtils : : getInteger ( m , " timeout " , CommandLine : : TimeoutNotSet ) ;
2018-01-29 21:08:42 +01:00
if ( ! command . isEmpty ( ) )
return CommandLine ( command , timeout ) ;
2018-02-12 16:20:03 +01:00
cWarning ( ) < < " Bad CommandLine element " < < m ;
2018-01-29 21:08:42 +01:00
return CommandLine ( ) ;
}
2018-01-29 21:25:18 +01:00
static CommandList_t get_variant_stringlist ( const QVariantList & l )
2018-01-15 11:59:44 +01:00
{
2018-01-29 17:01:28 +01:00
CommandList_t retl ;
2019-04-11 13:09:01 +02:00
unsigned int count = 0 ;
2018-01-15 11:59:44 +01:00
for ( const auto & v : l )
{
if ( v . type ( ) = = QVariant : : String )
2018-01-29 21:25:18 +01:00
retl . append ( CommandLine ( v . toString ( ) , CommandLine : : TimeoutNotSet ) ) ;
2018-01-29 21:08:42 +01:00
else if ( v . type ( ) = = QVariant : : Map )
{
2019-04-11 13:09:01 +02:00
auto command ( get_variant_object ( v . toMap ( ) ) ) ;
if ( command . isValid ( ) )
retl . append ( command ) ;
2018-01-29 21:08:42 +01:00
// Otherwise warning is already given
}
2018-01-15 11:59:44 +01:00
else
2019-04-11 13:09:01 +02:00
cWarning ( ) < < " Bad CommandList element " < < count < < v . type ( ) < < v ;
+ + count ;
2018-01-15 11:59:44 +01:00
}
return retl ;
}
2018-01-29 17:01:28 +01:00
CommandList : : CommandList ( bool doChroot , int timeout )
2018-01-15 11:59:44 +01:00
: m_doChroot ( doChroot )
2018-01-29 17:01:28 +01:00
, m_timeout ( timeout )
2018-01-15 11:59:44 +01:00
{
}
2018-01-29 17:01:28 +01:00
CommandList : : CommandList : : CommandList ( const QVariant & v , bool doChroot , int timeout )
: CommandList ( doChroot , timeout )
2018-01-15 11:59:44 +01:00
{
if ( v . type ( ) = = QVariant : : List )
{
const auto v_list = v . toList ( ) ;
if ( v_list . count ( ) )
2018-01-29 21:25:18 +01:00
append ( get_variant_stringlist ( v_list ) ) ;
2018-01-15 11:59:44 +01:00
else
2018-02-12 16:20:03 +01:00
cWarning ( ) < < " Empty CommandList " ;
2018-01-15 11:59:44 +01:00
}
else if ( v . type ( ) = = QVariant : : String )
append ( v . toString ( ) ) ;
2018-01-29 21:08:42 +01:00
else if ( v . type ( ) = = QVariant : : Map )
{
auto c ( get_variant_object ( v . toMap ( ) ) ) ;
if ( c . isValid ( ) )
append ( c ) ;
// Otherwise warning is already given
}
2018-01-15 11:59:44 +01:00
else
2018-02-12 16:20:03 +01:00
cWarning ( ) < < " CommandList does not understand variant " < < v . type ( ) ;
2018-01-15 11:59:44 +01:00
}
CommandList : : ~ CommandList ( )
{
}
2018-05-23 15:25:57 +02:00
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 ;
}
2018-02-07 17:12:49 +01:00
Calamares : : JobResult CommandList : : run ( )
2018-01-15 11:59:44 +01:00
{
2018-05-16 17:20:40 +02:00
QLatin1Literal rootMagic ( " @@ROOT@@ " ) ;
2018-05-23 15:25:57 +02:00
QLatin1Literal userMagic ( " @@USER@@ " ) ;
2018-05-16 17:20:40 +02:00
2018-01-15 11:59:44 +01:00
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 ( ) ;
2018-05-16 17:20:40 +02:00
2018-05-23 15:25:57 +02:00
bool needsRootSubstitution = findInCommands ( * this , rootMagic ) ;
2018-05-16 17:20:40 +02:00
if ( needsRootSubstitution & & ( location = = System : : RunLocation : : RunInHost ) )
2018-01-15 11:59:44 +01:00
{
if ( ! gs | | ! gs - > contains ( " rootMountPoint " ) )
{
2018-02-12 16:20:03 +01:00
cError ( ) < < " No rootMountPoint defined. " ;
2018-02-07 17:03:55 +01:00
return Calamares : : JobResult : : error ( QCoreApplication : : translate ( " CommandList " , " Could not run command. " ) ,
2018-05-16 17:20:40 +02:00
QCoreApplication : : translate ( " CommandList " , " The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined. " ) ) ;
2018-01-15 11:59:44 +01:00
}
root = gs - > value ( " rootMountPoint " ) . toString ( ) ;
}
2018-05-23 15:25:57 +02:00
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
2018-01-15 11:59:44 +01:00
for ( CommandList : : const_iterator i = cbegin ( ) ; i ! = cend ( ) ; + + i )
{
2018-01-29 17:01:28 +01:00
QString processed_cmd = i - > command ( ) ;
2018-05-23 15:25:57 +02:00
processed_cmd . replace ( rootMagic , root ) . replace ( userMagic , user ) ;
2018-01-15 11:59:44 +01:00
bool suppress_result = false ;
if ( processed_cmd . startsWith ( ' - ' ) )
{
suppress_result = true ;
2018-01-29 21:25:18 +01:00
processed_cmd . remove ( 0 , 1 ) ; // Drop the -
2018-01-15 11:59:44 +01:00
}
QStringList shell_cmd { " /bin/sh " , " -c " } ;
shell_cmd < < processed_cmd ;
2018-01-29 21:25:18 +01:00
int timeout = i - > timeout ( ) > = 0 ? i - > timeout ( ) : m_timeout ;
2018-01-15 11:59:44 +01:00
ProcessResult r = System : : runCommand (
2018-01-29 21:25:18 +01:00
location , shell_cmd , QString ( ) , QString ( ) , timeout ) ;
2018-01-15 11:59:44 +01:00
if ( r . getExitCode ( ) ! = 0 )
{
if ( suppress_result )
2018-01-15 14:41:24 +01:00
cDebug ( ) < < " Error code " < < r . getExitCode ( ) < < " ignored by CommandList configuration. " ;
2018-01-15 11:59:44 +01:00
else
2018-02-07 17:12:49 +01:00
return r . explainProcess ( processed_cmd , timeout ) ;
2018-01-15 11:59:44 +01:00
}
}
return Calamares : : JobResult : : ok ( ) ;
}
2018-01-29 17:01:28 +01:00
void
CommandList : : append ( const QString & s )
{
append ( CommandLine ( s , m_timeout ) ) ;
}
2018-01-15 11:59:44 +01:00
} // namespace