1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
/*
* 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;
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);
if(key_end == std::string::npos) {
/* Key without value */
any_error = true;
output_error("installfile:" + std::to_string(lineno),
"key '" + line.substr(start) + "' 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;
}
}
|