source: calamares/trunk/fuentes/src/libcalamares/utils/CommandList.cpp @ 7538

Last change on this file since 7538 was 7538, checked in by kbut, 17 months ago

sync with github

File size: 5.8 KB
Line 
1/* === This file is part of Calamares - <https://github.com/calamares> ===
2 *
3 *   Copyright 2018, Adriaan de Groot <groot@kde.org>
4 *
5 *   Calamares is free software: you can redistribute it and/or modify
6 *   it under the terms of the GNU General Public License as published by
7 *   the Free Software Foundation, either version 3 of the License, or
8 *   (at your option) any later version.
9 *
10 *   Calamares is distributed in the hope that it will be useful,
11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 *   GNU General Public License for more details.
14 *
15 *   You should have received a copy of the GNU General Public License
16 *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "CommandList.h"
20
21#include "GlobalStorage.h"
22#include "JobQueue.h"
23
24#include "utils/CalamaresUtils.h"
25#include "utils/CalamaresUtilsSystem.h"
26#include "utils/Logger.h"
27
28#include <QCoreApplication>
29#include <QVariantList>
30
31namespace CalamaresUtils
32{
33
34static CommandLine get_variant_object( const QVariantMap& m )
35{
36    QString command = CalamaresUtils::getString( m, "command" );
37    int timeout = CalamaresUtils::getInteger( m, "timeout", CommandLine::TimeoutNotSet );
38
39    if ( !command.isEmpty() )
40        return CommandLine( command, timeout );
41    cWarning() << "Bad CommandLine element" << m;
42    return CommandLine();
43}
44
45static CommandList_t get_variant_stringlist( const QVariantList& l )
46{
47    CommandList_t retl;
48    unsigned int c = 0;
49    for ( const auto& v : l )
50    {
51        if ( v.type() == QVariant::String )
52            retl.append( CommandLine( v.toString(), CommandLine::TimeoutNotSet ) );
53        else if ( v.type() == QVariant::Map )
54        {
55            auto c( get_variant_object( v.toMap() ) );
56            if ( c.isValid() )
57                retl.append( c );
58            // Otherwise warning is already given
59        }
60        else
61            cWarning() << "Bad CommandList element" << c << v.type() << v;
62        ++c;
63    }
64    return retl;
65}
66
67CommandList::CommandList( bool doChroot, int timeout )
68    : m_doChroot( doChroot )
69    , m_timeout( timeout )
70{
71}
72
73CommandList::CommandList::CommandList( const QVariant& v, bool doChroot, int timeout )
74    : CommandList( doChroot, timeout )
75{
76    if ( v.type() == QVariant::List )
77    {
78        const auto v_list = v.toList();
79        if ( v_list.count() )
80            append( get_variant_stringlist( v_list ) );
81        else
82            cWarning() << "Empty CommandList";
83    }
84    else if ( v.type() == QVariant::String )
85        append( v.toString() );
86    else if ( v.type() == QVariant::Map )
87    {
88        auto c( get_variant_object( v.toMap() ) );
89        if ( c.isValid() )
90            append( c );
91        // Otherwise warning is already given
92    }
93    else
94        cWarning() << "CommandList does not understand variant" << v.type();
95}
96
97CommandList::~CommandList()
98{
99}
100
101static inline bool
102findInCommands( const CommandList& l, const QString& needle )
103{
104    for ( CommandList::const_iterator i = l.cbegin(); i != l.cend(); ++i )
105        if ( i->command().contains( needle ) )
106            return true;
107    return false;
108}
109
110Calamares::JobResult CommandList::run()
111{
112    QLatin1Literal rootMagic( "@@ROOT@@" );
113    QLatin1Literal userMagic( "@@USER@@" );
114
115    System::RunLocation location = m_doChroot ? System::RunLocation::RunInTarget : System::RunLocation::RunInHost;
116
117    /* Figure out the replacement for @@ROOT@@ */
118    QString root = QStringLiteral( "/" );
119    Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
120
121    bool needsRootSubstitution = findInCommands( *this, rootMagic );
122    if ( needsRootSubstitution && ( location == System::RunLocation::RunInHost ) )
123    {
124        if ( !gs || !gs->contains( "rootMountPoint" ) )
125        {
126            cError() << "No rootMountPoint defined.";
127            return Calamares::JobResult::error( QCoreApplication::translate( "CommandList", "Could not run command." ),
128                                                QCoreApplication::translate( "CommandList", "The command runs in the host environment and needs to know the root path, but no rootMountPoint is defined." ) );
129        }
130        root = gs->value( "rootMountPoint" ).toString();
131    }
132
133    bool needsUserSubstitution = findInCommands( *this, userMagic );
134    if ( needsUserSubstitution && ( !gs || !gs->contains( "username" ) ) )
135    {
136        cError() << "No username defined.";
137        return Calamares::JobResult::error(
138            QCoreApplication::translate( "CommandList", "Could not run command." ),
139            QCoreApplication::translate( "CommandList", "The command needs to know the user's name, but no username is defined." ) );
140    }
141    QString user = gs->value( "username" ).toString();  // may be blank if unset
142
143    for ( CommandList::const_iterator i = cbegin(); i != cend(); ++i )
144    {
145        QString processed_cmd = i->command();
146        processed_cmd.replace( rootMagic, root ).replace( userMagic, user );
147        bool suppress_result = false;
148        if ( processed_cmd.startsWith( '-' ) )
149        {
150            suppress_result = true;
151            processed_cmd.remove( 0, 1 );  // Drop the -
152        }
153
154        QStringList shell_cmd { "/bin/sh", "-c" };
155        shell_cmd << processed_cmd;
156
157        int timeout = i->timeout() >= 0 ? i->timeout() : m_timeout;
158        ProcessResult r = System::runCommand(
159                              location, shell_cmd, QString(), QString(), timeout );
160
161        if ( r.getExitCode() != 0 )
162        {
163            if ( suppress_result )
164                cDebug() << "Error code" << r.getExitCode() << "ignored by CommandList configuration.";
165            else
166                return r.explainProcess( processed_cmd, timeout );
167        }
168    }
169
170    return Calamares::JobResult::ok();
171}
172
173void
174CommandList::append( const QString& s )
175{
176    append( CommandLine( s, m_timeout ) );
177}
178
179}  // namespace
Note: See TracBrowser for help on using the repository browser.