summaryrefslogblamecommitdiff
path: root/hscript/script.cc
blob: e7746bc41254cb739c88901d44d436f356ab1185 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                                                           

                   
                    
                  


                     
 



                         


                              
                                                          
                                                    
                                        
                                                      


                                                        
                                                          

                                                                


                  
                                 

 
                                                                  
                             
               

                                                         



                                    

 





                                                                       
                           








                                                        
                                                           






                                                   

                                                                              
                                   
                             
                                                                 

                                                                
                                                  


                                                          


         




                          















                                                                              

 
                               
                 


 
/*
 * script.hh - Implementation of the Script class
 * libhscript, the HorizonScript library for
 * Project Horizon
 *
 * Copyright (c) 2019 Adélie Linux and contributors.  All rights reserved.
 * This code is licensed under the AGPL 3.0 license, as noted in the
 * LICENSE-code file in the root directory of this repository.
 *
 * SPDX-License-Identifier: AGPL-3.0-only
 */

#include <fstream>
#include <iostream>
#include "script.hh"
#include "disk.hh"
#include "meta.hh"
#include "network.hh"
#include "user.hh"

#include "util/output.hh"

#define LINE_MAX 512

namespace Horizon {

struct Script::ScriptPrivate {
    /*! Determines whether or not to enable networking. */
    std::unique_ptr<Horizon::Keys::Network> network;
    /*! The target system's hostname. */
    std::unique_ptr<Horizon::Keys::Hostname> hostname;
    /*! The packages to install to the target system. */
    std::vector<std::string> packages;
    /*! The root shadow line. */
    std::unique_ptr<Horizon::Keys::RootPassphrase> rootpw;
    /*! Target system's mountpoints. */
    std::vector< std::unique_ptr<Horizon::Keys::Mount> > mounts;
};

Script::Script() {
    internal = new ScriptPrivate;
}

const Script *Script::load(std::string path, ScriptOptions opts) {
    std::ifstream file(path);
    if(!file) {
        output_error(path, "Cannot open installfile", "",
                     (opts.test(Pretty)));
        return nullptr;
    }

    return Script::load(file, opts);
}

const Script *Script::load(std::istream &sstream, ScriptOptions opts) {
    Script *the_script = new Script;

    int lineno = 0;
    char nextline[LINE_MAX];
    const std::string delim(" \t");
    bool any_error = false;

    while(sstream.getline(nextline, sizeof(nextline))) {
        lineno++;
        if(nextline[0] == '#') {
            /* This is a comment line; ignore it. */
            continue;
        }

        const std::string line(nextline);
        std::string::size_type start, key_end, value_begin;
        start = line.find_first_not_of(delim);
        if(start == std::string::npos) {
            /* This is a blank line; ignore it. */
            continue;
        }

        key_end = line.find_first_of(delim, start);
        value_begin = line.find_first_not_of(delim, key_end);
        if(key_end == std::string::npos || value_begin == std::string::npos) {
            /* Key without value */
            any_error = true;
            output_error("installfile:" + std::to_string(lineno),
                         "key '" + line.substr(start, key_end) +
                             "' has no value",
                         "", (opts.test(Pretty)));
            if(!opts.test(ScriptOptionFlags::KeepGoing)) {
                break;
            }
        }
    }

    if(any_error) {
        delete the_script;
        return nullptr;
    }

    if(sstream.fail() && !sstream.eof()) {
        output_error("installfile:" + std::to_string(lineno + 1),
                     "line exceeds maximum length",
                     "Maximum length for line is " + std::to_string(LINE_MAX),
                     (opts.test(Pretty)));
        delete the_script;
        return nullptr;
    }

    if(sstream.bad() && !sstream.eof()) {
        output_error("installfile:" + std::to_string(lineno),
                     "I/O error reading installfile", "",
                     (opts.test(Pretty)));
    }

    return the_script;
}

bool Script::validate() const {
    return false;
}

}