summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--hscript/script.cc74
-rw-r--r--hscript/script.hh29
-rw-r--r--tests/scripts/0017-line-too-long.installfile5
-rw-r--r--tools/hscript-validate/validator.cc39
-rw-r--r--util/output.hh39
6 files changed, 157 insertions, 31 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac98dfb..b854c6e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,5 +10,7 @@ pkg_check_modules(LIBUDEV REQUIRED libudev)
pkg_check_modules(PARTED REQUIRED libparted)
find_library(BCNM_LIBRARY REQUIRED wpactrl PATH_SUFFIXES bcnm)
+include_directories(.)
+
add_subdirectory(hscript)
add_subdirectory(tools)
diff --git a/hscript/script.cc b/hscript/script.cc
index 748b09a..a9c39ab 100644
--- a/hscript/script.cc
+++ b/hscript/script.cc
@@ -18,6 +18,10 @@
#include "network.hh"
#include "user.hh"
+#include "util/output.hh"
+
+#define LINE_MAX 512
+
namespace Horizon {
struct Script::ScriptPrivate {
@@ -34,35 +38,67 @@ struct Script::ScriptPrivate {
};
Script::Script() {
+ internal = new ScriptPrivate;
}
const Script *Script::load(std::string path, ScriptOptions opts) {
- std::ifstream file;
- std::string maybe_error;
-
- file.exceptions(std::ios::badbit);
- try {
- file.open(path);
- } catch(const std::ios::failure &error) {
- maybe_error = error.what();
- } catch(const std::exception &error) {
- maybe_error = error.what();
- }
+ std::ifstream file(path);
if(!file) {
- std::cerr << "Cannot open installfile at \"" << path << "\": ";
- std::cerr << maybe_error;
- std::cerr << std::endl;
+ output_error(path, "Cannot open installfile", "",
+ (opts.test(Pretty)));
return nullptr;
}
return Script::load(file, opts);
}
-const Script *Script::load(std::istream &, ScriptOptions) {
- Script *foo = new Script;
- delete foo;
- std::cout << "loaded" << std::endl;
- return nullptr;
+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");
+
+ 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 */
+ output_error("installfile:" + std::to_string(lineno),
+ "key '" + line.substr(start) + "' has no value",
+ "", (opts.test(Pretty)));
+ }
+ }
+
+ 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() {
diff --git a/hscript/script.hh b/hscript/script.hh
index 1150e78..8c0f619 100644
--- a/hscript/script.hh
+++ b/hscript/script.hh
@@ -16,24 +16,29 @@
#include <string>
#include <vector>
#include <memory>
+#include <bitset>
namespace Horizon {
/**** Script option flags ****/
-/*! Don't stop after the first error. */
-#define SCRIPT_KEEP_GOING 0x0001
-/*! Ensure network resources are available. */
-#define SCRIPT_USE_NETWORK 0x0002
-/*! Treat warnings as errors. */
-#define SCRIPT_STRICT_MODE 0x0004
-/*! This is an Installation Environment - validate more keys. */
-#define SCRIPT_INSTALL_ENV 0x0008
-/*! "Pretty" output - used in interactive tooling only. */
-#define SCRIPT_PRETTY 0x0010
+enum ScriptOptionFlags {
+ /*! Don't stop after the first error. */
+ KeepGoing,
+ /*! Ensure network resources are available. */
+ UseNetwork,
+ /*! Treat warnings as errors. */
+ StrictMode,
+ /*! This is an Installation Environment - validate more keys. */
+ InstallEnvironment,
+ /*! "Pretty" output - used in interactive tooling only. */
+ Pretty,
+ /*! Count of flags */
+ NumFlags
+};
-typedef uint32_t ScriptOptions;
+typedef std::bitset<ScriptOptionFlags::NumFlags> ScriptOptions;
/*! Defines the Script class, which represents a HorizonScript. */
@@ -61,7 +66,7 @@ public:
private:
struct ScriptPrivate;
/*! Internal data. */
- const std::unique_ptr<ScriptPrivate> internal;
+ ScriptPrivate *internal;
};
}
diff --git a/tests/scripts/0017-line-too-long.installfile b/tests/scripts/0017-line-too-long.installfile
new file mode 100644
index 0000000..f208b5f
--- /dev/null
+++ b/tests/scripts/0017-line-too-long.installfile
@@ -0,0 +1,5 @@
+network true
+hostname test.machine
+pkginstall abiword abuild-doc adelie-base adelie-keys adelie-wallpapers alegreya alsa-utils anonymous-pro apk-tools-static at at-doc audacious audacious-dbg audacious-dev audacious-plugins audacious-plugins-dbg bash-binsh bash-doc bc bind-tools binutils-doc bsdwhois bubblewrap-nosuid build-tools calligra cargo checkbashisms chelf chrony clearsans cmd:mkfs.vfat cmd:wish command-not-found console-keymaps console-setup-doc consolekit2 consolekit2-dbg cryptsetup cups dash debianutils-which dejagnu dhcpcd dosfstools dracut dracut-doc dracut-lvm e2fsprogs e2fsprogs-doc easy-kernel-power8 easy-kernel-power8-modules ebgaramond emacs-nox essays1743 eudev-dev evince fantasque-sans-mono fastjar ffmpeg ffmpeg-doc ffmpeg-libs fifth-leg fira fira-code firefox-esr flex free42 fuse-exfat gcc-doc gcompat gdb git-doc git-email gnumeric gnupg gptfdisk grub grub-ieee1275 gutenprint gwenview hdparm heirloom-devtools hermit heuristica-otf htop hunkyfonts hunspell imagemagick iproute2 iproute2-doc iputils iso-codes jpegoptim kate-dbg kbd kbd-keymaps kcachegrind kde-graphics kde-gtk-config kde-system kde-utilities kdeplasma-addons kgpg khelpcenter klickety kmix kolourpaint konsole kpat krdc krita ksysguard-lang ktorrent ktorrent-doc kwin kwrite lame libedit-dbg libertine-fonts libreoffice-calc libx11-dbg lighttpd links linux-firmware-amdgpu linux-firmware-radeon linux-headers linux-pam-doc lm_sensors lmms lsof lvm2-doc lxqt-desktop lynx lz4 mac-fdisk make-doc marble mednaffe mesa-dbg mesa-demos mesa-demos-dbg mesa-dri-swrast meson minicom mkfontscale-doc modemmanager monoid montecarlo mozjs mtr mtr-gtk musl-dbg nano ncurses-terminfo netcat netifrc netifrc-doc netsurf nmap nmap-ncat node nvi oclock okteta okular opal-utils openjdk8 openrc openrc-doc openssh openssh-doc openssl oprofile oprofile-doc optipng otf-source-code-pro otf-source-sans-pro oxygen-icons5 papirus-icons parted parted-dev partitionmanager pciutils perl-app-licensecheck perl-json phonon-vlc php7 php7-curl php7-dom php7-json php7-openssl php7-simplexml pidgin pidgin-otr pigz pinentry-gtk pkgconf plasma-desktop plasma-desktop-doc postgresql procps-doc pulseaudio pulseaudio-alsa pulseaudio-dev purple-plugin-pack py3-docutils py3-lxml py3-mako py3-packaging py3-tox qastools qemu-riscv64 qemu-system-riscv64 qemu-user qpdfview qt-creator qt5-qtbase-dbg qt5-qtbase-dev qt5-qtdeclarative-dev qt5-qtpositioning qt5-qttools qt5-qtwebchannel quassel-client quassel-dbg rdesktop rpm2targz rsync ruby ruby-dbg ruby-irb rust s6-linux-init screen sg3_utils shadow-doc socat spectacle sqlite squashfs-tools ssmtp stdman strace systemsettings tcpdump tcpdump-doc texinfo the_silver_searcher thunderbird tigervnc tmux traceroute tree trigger-rally trojita ttc-iosevka ttf-dejavu ttf-liberation ttf-noto tzdata umbrello umbrello-doc urw-base35-fonts usbutils user-manager util-linux-doc utmps utmps-libs valgrind vimdiff vlc-plugins-lua vlc-pulse vlc-qt weechat weechat-python x11 x11vnc x264 xclip xf86-input-evdev xf86-video-ati xf86-video-ati-doc xf86-video-fbdev xfsprogs xfsprogs-doc xfwm4 xmlto xmoto xorg-fonts xorg-server xorg-server-xephyr xorg-server-xnest xorriso xterm youtube-dl zsh-doc
+rootpw $6$gumtLGmHwOVIRpQR$2M9PUO24hy5mofzWWf9a.YLbzOgOlUby1g0hDj.wG67E2wrrvys59fq02PPdxBdbgkLZFtjfEx6MHZwMBamwu/
+mount /dev/sda1 /
diff --git a/tools/hscript-validate/validator.cc b/tools/hscript-validate/validator.cc
index e69de29..e9e1979 100644
--- a/tools/hscript-validate/validator.cc
+++ b/tools/hscript-validate/validator.cc
@@ -0,0 +1,39 @@
+/*
+ * validator.cc - Implementation of the HorizonScript validation utility
+ * 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 "hscript/script.hh"
+#include "util/output.hh"
+
+int main(int argc, char *argv[]) {
+ const Horizon::Script *my_script;
+ Horizon::ScriptOptions opts;
+
+ if(argc < 2) {
+ output_error("hscript-validate", "No installfile specified", "", true);
+ std::cerr << "Run `" << argv[0] << " --help` for usage information." << std::endl;
+ return EXIT_FAILURE;
+ }
+
+ std::cout << "\033[1mHorizonScript Validation Utility version 0.1.0\033[0m" << std::endl;
+ std::cout << "Copyright (c) 2019 Adélie Linux and contributors. AGPL-3.0 license." << std::endl;
+ std::cout << std::endl;
+
+ opts.set(Horizon::ScriptOptionFlags::Pretty);
+
+ my_script = Horizon::Script::load(argv[1], opts);
+ if(my_script == nullptr) {
+ std::cout << "Could not load the specified script." << std::endl;
+ return EXIT_FAILURE;
+ }
+ delete my_script;
+
+ return EXIT_SUCCESS;
+}
diff --git a/util/output.hh b/util/output.hh
new file mode 100644
index 0000000..9281301
--- /dev/null
+++ b/util/output.hh
@@ -0,0 +1,39 @@
+/*
+ * output.hh - Miscellaneous output routines
+ * util, the utility 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 __HORIZON_OUTPUT_HH_
+#define __HORIZON_OUTPUT_HH_
+
+#include <string>
+#include <iostream>
+
+/*! Prints an error message to the cerr stream.
+ * @param where The location where the error occurred.
+ * @param message The error that occurred.
+ * @param detail Additional detail for the error, if available.
+ * @param pretty Whether or not to colourise (interactive output).
+ */
+inline void output_error(std::string where, std::string message,
+ std::string detail = "", bool pretty = false) {
+ std::cerr << where << ": ";
+ if(pretty) std::cerr << "\033[31;1m";
+ std::cerr << "error: ";
+ if(pretty) std::cerr << "\033[0;1m";
+ std::cerr << message;
+ if(pretty) std::cerr << "\033[0m";
+ if(!detail.empty()) {
+ std::cerr << ": " << detail;
+ }
+ std::cerr << std::endl;
+}
+
+#endif /* !__HORIZON_OUTPUT_HH_ */