summaryrefslogtreecommitdiff
path: root/hscript/script_i.hh
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2019-11-04 15:51:15 -0600
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2019-11-04 15:51:15 -0600
commit0e5d52b23ae0b86e938905a332ad5b7439011dcc (patch)
treef97ab264328bec2ccdb7a9e5b54f3357d1ef3988 /hscript/script_i.hh
parent5a44e287dd8a6142c7a2ad7ddbc0570554ab149b (diff)
downloadhorizon-0e5d52b23ae0b86e938905a332ad5b7439011dcc.tar.gz
horizon-0e5d52b23ae0b86e938905a332ad5b7439011dcc.tar.bz2
horizon-0e5d52b23ae0b86e938905a332ad5b7439011dcc.tar.xz
horizon-0e5d52b23ae0b86e938905a332ad5b7439011dcc.zip
hscript: Refactor script.cc and disk.cc for maintainability
Diffstat (limited to 'hscript/script_i.hh')
-rw-r--r--hscript/script_i.hh289
1 files changed, 289 insertions, 0 deletions
diff --git a/hscript/script_i.hh b/hscript/script_i.hh
new file mode 100644
index 0000000..cb7da13
--- /dev/null
+++ b/hscript/script_i.hh
@@ -0,0 +1,289 @@
+/*
+ * script_i.hh - Implementation of internal doodads for 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
+ */
+
+#ifndef HSCRIPT_SCRIPT_INTERNAL_HH_
+#define HSCRIPT_SCRIPT_INTERNAL_HH_
+
+#include <assert.h>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "disk.hh"
+#include "meta.hh"
+#include "network.hh"
+#include "user.hh"
+
+using namespace Horizon::Keys;
+
+namespace Horizon {
+
+/*! Describes a user account. */
+struct UserDetail {
+ std::unique_ptr<Username> name;
+ std::unique_ptr<UserAlias> alias;
+ std::unique_ptr<UserPassphrase> passphrase;
+ std::unique_ptr<UserIcon> icon;
+ std::vector< std::unique_ptr<UserGroups> > groups;
+};
+
+struct Script::ScriptPrivate {
+ /*! Determines whether or not to enable networking. */
+ std::unique_ptr<Network> network;
+ /*! The target system's hostname. */
+ std::unique_ptr<Hostname> hostname;
+ /*! The packages to install to the target system. */
+ std::set<std::string> packages;
+ /*! The root shadow line. */
+ std::unique_ptr<RootPassphrase> rootpw;
+ /*! The system language. */
+ std::unique_ptr<Language> lang;
+ /*! The system keymap. */
+ std::unique_ptr<Keymap> keymap;
+ /*! The system timezone. */
+ std::unique_ptr<Timezone> tzone;
+
+ /*! Network addressing configuration */
+ std::vector< std::unique_ptr<NetAddress> > addresses;
+ /*! Network nameserver resolver addresses */
+ std::vector< std::unique_ptr<Nameserver> > nses;
+ /*! Wireless networking configuration */
+ std::vector< std::unique_ptr<NetSSID> > ssids;
+
+ /*! APK repositories */
+ std::vector< std::unique_ptr<Repository> > repos;
+ /*! APK repository keys */
+ std::vector< std::unique_ptr<SigningKey> > repo_keys;
+
+ /*! User account information */
+ std::map< std::string, std::unique_ptr<UserDetail> > accounts;
+
+ /*! Disk identification keys */
+ std::vector< std::unique_ptr<DiskId> > diskids;
+ /*! Disklabel configuration keys */
+ std::vector< std::unique_ptr<DiskLabel> > disklabels;
+ /*! Partition creation keys */
+ std::vector< std::unique_ptr<Partition> > partitions;
+ /*! LVM physical volume keys */
+ std::vector< std::unique_ptr<LVMPhysical> > lvm_pvs;
+ /*! LVM volume group keys */
+ std::vector< std::unique_ptr<LVMGroup> > lvm_vgs;
+ /*! LVM logical volume keys */
+ std::vector< std::unique_ptr<LVMVolume> > lvm_lvs;
+ /*! LUKS creation keys */
+ std::vector< std::unique_ptr<Encrypt> > luks;
+ /*! Filesystem creation keys */
+ std::vector< std::unique_ptr<Filesystem> > fses;
+ /*! Target system's mountpoints. */
+ std::vector< std::unique_ptr<Mount> > mounts;
+
+#ifdef NON_LIBRE_FIRMWARE
+ std::unique_ptr<Firmware> firmware;
+#endif
+
+ /*! Store +key_obj+ representing the key +key_name+.
+ * @param key_name The name of the key that is being stored.
+ * @param obj The Key object associated with the key.
+ * @param errors Output parameter: if given, incremented on error.
+ * @param warnings Output parameter: if given, incremented on warning.
+ * @param opts Script parsing options.
+ */
+ bool store_key(const std::string &key_name, Key *obj, int lineno,
+ int *errors, int *warnings, const ScriptOptions &opts);
+
+#define DUPLICATE_ERROR(OBJ, KEY, OLD_VAL) \
+ std::string err_str("previous value was ");\
+ err_str += OLD_VAL;\
+ err_str += " at installfile:" + std::to_string(OBJ->lineno());\
+ if(errors) *errors += 1;\
+ output_error("installfile:" + std::to_string(line),\
+ "duplicate value for key '" + std::string(KEY) + "'",\
+ err_str);
+
+ bool store_network(Key* obj, int line, int *errors, int *, ScriptOptions) {
+ if(network) {
+ DUPLICATE_ERROR(network, "network",
+ network->test() ? "true" : "false")
+ return false;
+ }
+ std::unique_ptr<Network> net(dynamic_cast<Network *>(obj));
+ network = std::move(net);
+ return true;
+ }
+
+ bool store_hostname(Key* obj, int line, int *errors, int *, ScriptOptions) {
+ if(hostname) {
+ DUPLICATE_ERROR(hostname, "hostname", hostname->value())
+ return false;
+ }
+ std::unique_ptr<Hostname> name(dynamic_cast<Hostname *>(obj));
+ hostname = std::move(name);
+ return true;
+ }
+
+ bool store_pkginstall(Key* obj, int line, int *, int *warnings,
+ ScriptOptions opts) {
+ PkgInstall *install = dynamic_cast<PkgInstall *>(obj);
+ for(auto &pkg : install->packages()) {
+ if(opts.test(StrictMode) && packages.find(pkg) != packages.end()) {
+ if(warnings) *warnings += 1;
+ output_warning("installfile:" + std::to_string(line),
+ "pkginstall: package '" + pkg +
+ "' has already been specified");
+ continue;
+ }
+ packages.insert(pkg);
+ }
+ delete install;
+ return true;
+ }
+
+ bool store_rootpw(Key* obj, int line, int *errors, int *, ScriptOptions) {
+ if(rootpw) {
+ DUPLICATE_ERROR(rootpw, "rootpw", "an encrypted passphrase")
+ return false;
+ }
+ std::unique_ptr<RootPassphrase> r(dynamic_cast<RootPassphrase *>(obj));
+ rootpw = std::move(r);
+ return true;
+ }
+
+ bool store_firmware(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ std::unique_ptr<Firmware> f(dynamic_cast<Firmware *>(obj));
+#ifdef NON_LIBRE_FIRMWARE
+ if(firmware) {
+ DUPLICATE_ERROR(firmware, "firmware",
+ (firmware->test()) ? "true" : "false")
+ return false;
+ }
+ firmware = std::move(f);
+ return true;
+#else
+ assert(!f->test());
+ return true;
+#endif
+ }
+
+ bool store_lang(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ if(lang) {
+ DUPLICATE_ERROR(lang, "language", lang->value())
+ return false;
+ }
+ std::unique_ptr<Language> l(dynamic_cast<Language *>(obj));
+ lang = std::move(l);
+ return true;
+ }
+
+ bool store_keymap(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ if(keymap) {
+ DUPLICATE_ERROR(keymap, "keymap", keymap->value())
+ return false;
+ }
+ std::unique_ptr<Keymap> k(dynamic_cast<Keymap *>(obj));
+ keymap = std::move(k);
+ return true;
+ }
+
+ bool store_timezone(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ if(tzone) {
+ DUPLICATE_ERROR(tzone, "timezone", tzone->value())
+ return false;
+ }
+ std::unique_ptr<Timezone> t(dynamic_cast<Timezone *>(obj));
+ tzone = std::move(t);
+ return true;
+ }
+
+ bool store_username(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ if(accounts.size() >= 255) {
+ if(errors) *errors += 1;
+ output_error("installfile:" + std::to_string(line),
+ "username: too many users",
+ "you may only specify 255 users");
+ return false;
+ }
+ std::unique_ptr<Username> name(dynamic_cast<Username *>(obj));
+ if(accounts.find(name->value()) != accounts.end()) {
+ DUPLICATE_ERROR((*accounts.find(name->value())).second->name,
+ "username", "assigned")
+ return false;
+ }
+ std::unique_ptr<UserDetail> detail(new UserDetail);
+ detail->name = std::move(name);
+ accounts.insert(std::make_pair(detail->name->value(),
+ std::move(detail)));
+ return true;
+ }
+
+#define GET_USER_DETAIL(OBJ, KEY) \
+ if(accounts.find(OBJ->username()) == accounts.end()) {\
+ if(errors) *errors += 1;\
+ output_error("installfile:" + std::to_string(line),\
+ std::string(KEY) + ": account name " + OBJ->username() +\
+ " is unknown");\
+ return false;\
+ }\
+ UserDetail *detail = (*accounts.find(OBJ->username())).second.get();
+
+ bool store_useralias(Key* obj, int line, int *errors, int *, ScriptOptions) {
+ std::unique_ptr<UserAlias> alias(dynamic_cast<UserAlias *>(obj));
+ GET_USER_DETAIL(alias, "useralias")
+ /* REQ: Runner.Validate.useralias.Unique */
+ if(detail->alias) {
+ DUPLICATE_ERROR(detail->alias, "useralias", detail->alias->alias())
+ return false;
+ }
+ detail->alias = std::move(alias);
+ return true;
+ }
+
+ bool store_userpw(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ std::unique_ptr<UserPassphrase> pw(dynamic_cast<UserPassphrase *>(obj));
+ GET_USER_DETAIL(pw, "userpw")
+ /* REQ: Runner.Validate.userpw.Unique */
+ if(detail->passphrase) {
+ DUPLICATE_ERROR(detail->passphrase, "userpw",
+ "an encrypted passphrase")
+ return false;
+ }
+ detail->passphrase = std::move(pw);
+ return true;
+ }
+
+ bool store_usericon(Key *obj, int line, int *errors, int *, ScriptOptions) {
+ std::unique_ptr<UserIcon> icon(dynamic_cast<UserIcon *>(obj));
+ GET_USER_DETAIL(icon, "usericon")
+ /* REQ: Runner.Validate.usericon.Unique */
+ if(detail->icon) {
+ DUPLICATE_ERROR(detail->icon, "usericon", detail->icon->icon())
+ return false;
+ }
+ detail->icon = std::move(icon);
+ return true;
+ }
+
+ bool store_usergroups(Key* obj, int line, int *errors, int *,
+ ScriptOptions) {
+ std::unique_ptr<UserGroups> grp(dynamic_cast<UserGroups *>(obj));
+ GET_USER_DETAIL(grp, "usergroups")
+ detail->groups.push_back(std::move(grp));
+ return true;
+ }
+#undef GET_USER_DETAIL
+
+#undef DUPLICATE_ERROR
+};
+
+}
+
+#endif /* !HSCRIPT_SCRIPT_INTERNAL_HH_ */