Compare commits
3 Commits
abbfd5825f
...
7c0ff8c75a
Author | SHA1 | Date | |
---|---|---|---|
7c0ff8c75a | |||
a11aa7a2d0 | |||
0abd9153ae |
@ -19,6 +19,7 @@ set(FREESTANDING_SOURCES
|
||||
src/SHA.cpp
|
||||
src/Stack.cpp
|
||||
src/String.cpp
|
||||
src/RefString.cpp
|
||||
src/StringBuilder.cpp
|
||||
src/StringView.cpp
|
||||
src/Utf8.cpp
|
||||
@ -51,6 +52,9 @@ add_library(luna ${SOURCES})
|
||||
target_compile_options(luna PRIVATE ${COMMON_FLAGS})
|
||||
target_include_directories(luna PUBLIC include/)
|
||||
target_include_directories(luna PUBLIC ${LUNA_BASE}/usr/include)
|
||||
if(DEFINED LIBC_BOOTSTRAP)
|
||||
target_compile_definitions(luna PUBLIC LIBC_BOOTSTRAP)
|
||||
endif()
|
||||
|
||||
if("${LUNA_ARCH}" MATCHES "x86_64")
|
||||
target_compile_options(luna-freestanding PRIVATE -mno-red-zone)
|
||||
|
120
libluna/include/luna/RefString.h
Normal file
120
libluna/include/luna/RefString.h
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @file RefString.h
|
||||
* @author apio (cloudapio.eu)
|
||||
* @brief Reference-counted, trivially-copyable, immutable string type.
|
||||
*
|
||||
* @copyright Copyright (c) 2024, the Luna authors.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <luna/Hash.h>
|
||||
#include <luna/Result.h>
|
||||
#include <luna/SharedPtr.h>
|
||||
#include <luna/String.h>
|
||||
#include <luna/StringView.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
class RefString
|
||||
{
|
||||
typedef const char* ConstIterator;
|
||||
|
||||
public:
|
||||
/* Constructs an empty String. */
|
||||
RefString();
|
||||
|
||||
RefString(RefString&&);
|
||||
|
||||
RefString(const RefString&);
|
||||
|
||||
RefString& operator=(const RefString&);
|
||||
|
||||
bool operator==(const RefString& other) const
|
||||
{
|
||||
return !compare(this, &other);
|
||||
}
|
||||
|
||||
~RefString() = default;
|
||||
|
||||
/* Creates a copy of a specific segment of this String and returns it. */
|
||||
Result<RefString> substring(usize begin, usize size) const;
|
||||
|
||||
/* Splits a String with a delimiter. */
|
||||
Result<Vector<RefString>> split(StringView delim) const
|
||||
{
|
||||
return view().ref_split(delim);
|
||||
}
|
||||
|
||||
/* Splits a String into two parts with a delimiter. */
|
||||
Result<Vector<RefString>> split_once(char delim) const
|
||||
{
|
||||
return view().ref_split_once(delim);
|
||||
}
|
||||
|
||||
/* Creates a single String consisting of a list of strings separated by a delimiter. */
|
||||
static Result<RefString> join(const Vector<RefString>& vec, StringView delim);
|
||||
|
||||
/* Creates a single String consisting of a list of strings separated by a delimiter. */
|
||||
static Result<RefString> join(const Vector<StringView>& vec, StringView delim);
|
||||
|
||||
static Result<RefString> format(StringView fmt, ...);
|
||||
static Result<RefString> vformat(StringView fmt, va_list ap);
|
||||
|
||||
static Result<RefString> from_cstring(const char* str);
|
||||
static Result<RefString> from_string_view(StringView str);
|
||||
static Result<RefString> from_string(const String& str);
|
||||
|
||||
static int compare(const RefString* a, const RefString* b);
|
||||
|
||||
const char* chars() const;
|
||||
|
||||
usize length() const
|
||||
{
|
||||
return m_string_data ? m_string_data->length : 0;
|
||||
}
|
||||
|
||||
bool is_empty() const
|
||||
{
|
||||
return length() == 0;
|
||||
}
|
||||
|
||||
StringView view() const
|
||||
{
|
||||
return { chars(), length() };
|
||||
}
|
||||
|
||||
const char& operator[](usize) const;
|
||||
|
||||
ConstIterator begin() const
|
||||
{
|
||||
return chars();
|
||||
}
|
||||
|
||||
ConstIterator end() const
|
||||
{
|
||||
return begin() + length();
|
||||
}
|
||||
|
||||
private:
|
||||
struct RefStringData : public Shareable
|
||||
{
|
||||
char* string { nullptr };
|
||||
usize length { 0 };
|
||||
|
||||
RefStringData(char* s, usize l) : Shareable(), string(s), length(l)
|
||||
{
|
||||
}
|
||||
|
||||
~RefStringData()
|
||||
{
|
||||
if (string) free_impl(string);
|
||||
}
|
||||
};
|
||||
|
||||
SharedPtr<RefStringData> m_string_data { nullptr };
|
||||
|
||||
static Result<RefString> adopt(char* c_str);
|
||||
static Result<RefString> adopt(char* c_str, usize length);
|
||||
};
|
||||
|
||||
template <> u64 hash(const RefString& value, u64 salt);
|
@ -4,6 +4,7 @@
|
||||
#include <luna/Vector.h>
|
||||
|
||||
class String;
|
||||
class RefString;
|
||||
|
||||
class StringView
|
||||
{
|
||||
@ -43,6 +44,8 @@ class StringView
|
||||
|
||||
Result<Vector<String>> split(StringView delim) const;
|
||||
Result<Vector<String>> split_once(char delim) const;
|
||||
Result<Vector<RefString>> ref_split(StringView delim) const;
|
||||
Result<Vector<RefString>> ref_split_once(char delim) const;
|
||||
Result<Vector<StringView>> split_view(char delim) const;
|
||||
|
||||
bool contains(char v) const;
|
||||
|
@ -420,35 +420,39 @@ void dump_heap_usage()
|
||||
dbgln("-- Heap memory in use: %zu bytes", alloc_used);
|
||||
}
|
||||
|
||||
// Otherwise, this is defined in libstdc++.
|
||||
#ifdef USE_FREESTANDING
|
||||
void* operator new(usize size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
return malloc_impl(size, false, false).value_or(nullptr);
|
||||
}
|
||||
|
||||
void* operator new[](usize size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
return malloc_impl(size, false, false).value_or(nullptr);
|
||||
}
|
||||
|
||||
void operator delete(void* p) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
||||
void operator delete[](void* p) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
||||
void operator delete(void* p, usize) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
||||
void operator delete[](void* p, usize) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
#if defined(USE_FREESTANDING) || defined(LIBC_BOOTSTRAP)
|
||||
#define WEAK
|
||||
#else
|
||||
#define WEAK __attribute__((weak))
|
||||
#endif
|
||||
|
||||
// If libstdc++ is linked, it should override these definitions.
|
||||
void* WEAK operator new(usize size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
return malloc_impl(size, false, false).value_or(nullptr);
|
||||
}
|
||||
|
||||
void* WEAK operator new[](usize size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
return malloc_impl(size, false, false).value_or(nullptr);
|
||||
}
|
||||
|
||||
void WEAK operator delete(void* p) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
||||
void WEAK operator delete[](void* p) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
||||
void WEAK operator delete(void* p, usize) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
||||
void WEAK operator delete[](void* p, usize) noexcept
|
||||
{
|
||||
free_impl(p);
|
||||
}
|
||||
|
122
libluna/src/RefString.cpp
Normal file
122
libluna/src/RefString.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
/**
|
||||
* @file RefString.cpp
|
||||
* @author apio (cloudapio.eu)
|
||||
* @brief Reference-counted, trivially-copyable, immutable string type.
|
||||
*
|
||||
* @copyright Copyright (c) 2024, the Luna authors.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <luna/Format.h>
|
||||
#include <luna/RefString.h>
|
||||
|
||||
static const char empty_string[] = { 0 };
|
||||
|
||||
RefString::RefString()
|
||||
{
|
||||
}
|
||||
|
||||
RefString::RefString(RefString&& other) : m_string_data(move(other.m_string_data))
|
||||
{
|
||||
}
|
||||
|
||||
RefString::RefString(const RefString& other) : m_string_data(other.m_string_data)
|
||||
{
|
||||
}
|
||||
|
||||
const char* RefString::chars() const
|
||||
{
|
||||
if (m_string_data) return m_string_data->string;
|
||||
return empty_string;
|
||||
}
|
||||
|
||||
RefString& RefString::operator=(const RefString& other)
|
||||
{
|
||||
if (&other == this) return *this;
|
||||
m_string_data = other.m_string_data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Result<RefString> RefString::substring(usize begin, usize size) const
|
||||
{
|
||||
if (begin + size >= size) return err(EINVAL);
|
||||
char* const dup = strndup(chars() + begin, size);
|
||||
if (!dup) return err(ENOMEM);
|
||||
return adopt(dup, size);
|
||||
}
|
||||
|
||||
const char& RefString::operator[](usize index) const
|
||||
{
|
||||
expect(index < length(), "index out of range");
|
||||
return chars()[index];
|
||||
}
|
||||
|
||||
Result<RefString> RefString::format(StringView fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
||||
auto rc = vformat(fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result<RefString> RefString::vformat(StringView fmt, va_list ap)
|
||||
{
|
||||
Vector<char> buf;
|
||||
|
||||
TRY(cstyle_format(
|
||||
fmt.chars(), [](char c, void* data) -> Result<void> { return ((Vector<char>*)data)->try_append(c); }, &buf,
|
||||
ap));
|
||||
|
||||
TRY(buf.try_append(0));
|
||||
|
||||
return adopt(buf.release_data());
|
||||
}
|
||||
|
||||
Result<RefString> RefString::from_cstring(const char* str)
|
||||
{
|
||||
return from_string_view(StringView { str });
|
||||
}
|
||||
|
||||
Result<RefString> RefString::from_string(const String& str)
|
||||
{
|
||||
return from_string_view(str.view());
|
||||
}
|
||||
|
||||
Result<RefString> RefString::from_string_view(StringView str)
|
||||
{
|
||||
char* const dup = strndup(str.chars(), str.length());
|
||||
if (!dup) return err(ENOMEM);
|
||||
return adopt(dup, str.length());
|
||||
}
|
||||
|
||||
int RefString::compare(const RefString* a, const RefString* b)
|
||||
{
|
||||
return strcmp(a->chars(), b->chars());
|
||||
}
|
||||
|
||||
Result<RefString> RefString::adopt(char* c_str)
|
||||
{
|
||||
return adopt(c_str, strlen(c_str));
|
||||
}
|
||||
|
||||
Result<RefString> RefString::adopt(char* c_str, usize length)
|
||||
{
|
||||
auto guard = make_scope_guard([&] { free_impl(c_str); });
|
||||
|
||||
auto data = TRY(make_shared<RefStringData>(c_str, length));
|
||||
|
||||
guard.deactivate();
|
||||
|
||||
RefString string;
|
||||
string.m_string_data = data;
|
||||
return string;
|
||||
}
|
||||
|
||||
template <> u64 hash(const RefString& value, u64 salt)
|
||||
{
|
||||
return hash_memory(value.chars(), value.length(), salt);
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include <luna/CString.h>
|
||||
#include <luna/NumberParsing.h>
|
||||
#include <luna/RefString.h>
|
||||
#include <luna/ScopeGuard.h>
|
||||
#include <luna/String.h>
|
||||
#include <luna/StringView.h>
|
||||
@ -86,6 +87,32 @@ Result<Vector<String>> StringView::split(StringView delim) const
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<Vector<RefString>> StringView::ref_split(StringView delim) const
|
||||
{
|
||||
Vector<RefString> result;
|
||||
RefString str;
|
||||
|
||||
char* copy = strndup(m_string, m_length);
|
||||
auto guard = make_scope_guard([copy] { free_impl(copy); });
|
||||
|
||||
char* segment = strtok(copy, delim.chars());
|
||||
if (!segment) return result;
|
||||
|
||||
str = TRY(RefString::from_cstring(segment));
|
||||
TRY(result.try_append(move(str)));
|
||||
|
||||
while (true)
|
||||
{
|
||||
segment = strtok(nullptr, delim.chars());
|
||||
if (!segment) return result;
|
||||
|
||||
str = TRY(RefString::from_cstring(segment));
|
||||
TRY(result.try_append(move(str)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<Vector<String>> StringView::split_once(char delim) const
|
||||
{
|
||||
Vector<String> result;
|
||||
@ -112,6 +139,32 @@ Result<Vector<String>> StringView::split_once(char delim) const
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<Vector<RefString>> StringView::ref_split_once(char delim) const
|
||||
{
|
||||
Vector<RefString> result;
|
||||
|
||||
char* copy = strndup(m_string, m_length);
|
||||
auto guard = make_scope_guard([copy] { free_impl(copy); });
|
||||
|
||||
char* middle = strchr(copy, delim);
|
||||
if (!middle)
|
||||
{
|
||||
auto str = TRY(RefString::from_cstring(copy));
|
||||
TRY(result.try_append(move(str)));
|
||||
return result;
|
||||
}
|
||||
|
||||
*middle = '\0';
|
||||
|
||||
auto begin = TRY(RefString::from_cstring(copy));
|
||||
auto end = TRY(RefString::from_cstring(middle + 1));
|
||||
|
||||
TRY(result.try_append(move(begin)));
|
||||
TRY(result.try_append(move(end)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Result<Vector<StringView>> StringView::split_view(char delim) const
|
||||
{
|
||||
Vector<StringView> result;
|
||||
|
@ -20,6 +20,7 @@ set(SOURCES
|
||||
src/IPC.cpp
|
||||
src/SharedMemory.cpp
|
||||
src/Timer.cpp
|
||||
src/Config.cpp
|
||||
)
|
||||
|
||||
add_library(os ${SOURCES})
|
||||
|
43
libos/include/os/Config.h
Normal file
43
libos/include/os/Config.h
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* @file Config.h
|
||||
* @author apio (cloudapio.eu)
|
||||
* @brief Configuration file parsing.
|
||||
*
|
||||
* @copyright Copyright (c) 2024, the Luna authors.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <luna/HashMap.h>
|
||||
#include <luna/RefString.h>
|
||||
#include <os/File.h>
|
||||
#include <os/Path.h>
|
||||
|
||||
namespace os
|
||||
{
|
||||
class ConfigFile
|
||||
{
|
||||
public:
|
||||
static Result<OwnedPtr<ConfigFile>> open(os::Path path);
|
||||
|
||||
Option<StringView> read_string(StringView key);
|
||||
StringView read_string_or(StringView key, StringView default_value);
|
||||
|
||||
Option<i64> read_number(StringView key);
|
||||
i64 read_number_or(StringView key, i64 default_value);
|
||||
|
||||
Option<bool> read_boolean(StringView key);
|
||||
bool read_boolean_or(StringView key, bool default_value);
|
||||
|
||||
Result<void> write_string(StringView key, StringView value);
|
||||
Result<void> write_number(StringView key, int value);
|
||||
Result<void> write_boolean(StringView key, bool value);
|
||||
|
||||
Result<void> sync();
|
||||
|
||||
private:
|
||||
os::Path m_path { "" };
|
||||
|
||||
HashMap<RefString, RefString> m_data;
|
||||
};
|
||||
}
|
139
libos/src/Config.cpp
Normal file
139
libos/src/Config.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/**
|
||||
* @file Config.cpp
|
||||
* @author apio (cloudapio.eu)
|
||||
* @brief Configuration file parsing.
|
||||
*
|
||||
* @copyright Copyright (c) 2024, the Luna authors.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <os/Config.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace os
|
||||
{
|
||||
Result<OwnedPtr<ConfigFile>> ConfigFile::open(os::Path path)
|
||||
{
|
||||
auto config = TRY(make_owned<ConfigFile>());
|
||||
|
||||
config->m_path = path;
|
||||
|
||||
auto file = TRY(os::File::open(path, os::File::ReadOnly));
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto line = TRY(file->read_line());
|
||||
if (line.is_empty()) break;
|
||||
|
||||
line.trim("\n");
|
||||
if (line.is_empty()) continue;
|
||||
|
||||
auto parts = TRY(line.split_once('='));
|
||||
if (parts.size() < 2 || parts[0].is_empty() || parts[1].is_empty()) return err(EINVAL);
|
||||
|
||||
auto key = TRY(RefString::from_string(parts[0]));
|
||||
auto value = TRY(RefString::from_string(parts[1]));
|
||||
|
||||
config->m_data.try_set(key, value);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
Option<StringView> ConfigFile::read_string(StringView key)
|
||||
{
|
||||
auto string = RefString::from_string_view(key).release_value();
|
||||
auto* value = m_data.try_get_ref(string);
|
||||
|
||||
if (!value) return {};
|
||||
|
||||
return value->view();
|
||||
}
|
||||
|
||||
StringView ConfigFile::read_string_or(StringView key, StringView default_value)
|
||||
{
|
||||
return read_string(key).value_or(default_value);
|
||||
}
|
||||
|
||||
Option<i64> ConfigFile::read_number(StringView key)
|
||||
{
|
||||
auto maybe_string = read_string(key);
|
||||
|
||||
if (!maybe_string.has_value()) return {};
|
||||
|
||||
auto string = maybe_string.value();
|
||||
|
||||
char* endptr;
|
||||
|
||||
i64 result = strtol(string.chars(), &endptr, 10);
|
||||
|
||||
if (string.chars() == endptr) return {};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
i64 ConfigFile::read_number_or(StringView key, i64 default_value)
|
||||
{
|
||||
return read_number(key).value_or(default_value);
|
||||
}
|
||||
|
||||
Option<bool> ConfigFile::read_boolean(StringView key)
|
||||
{
|
||||
auto maybe_string = read_string(key);
|
||||
|
||||
if (!maybe_string.has_value()) return {};
|
||||
|
||||
auto string = maybe_string.value();
|
||||
|
||||
if (string == "true" || string.to_uint().value_or(0) == 1) return true;
|
||||
if (string == "false" || string.to_uint().value_or(1) == 0) return false;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
bool ConfigFile::read_boolean_or(StringView key, bool default_value)
|
||||
{
|
||||
return read_boolean(key).value_or(default_value);
|
||||
}
|
||||
|
||||
Result<void> ConfigFile::write_string(StringView key, StringView value)
|
||||
{
|
||||
auto key_string = TRY(RefString::from_string_view(key));
|
||||
auto value_string = TRY(RefString::from_string_view(value));
|
||||
|
||||
auto worked = TRY(m_data.try_set(key_string, value_string));
|
||||
if (!worked)
|
||||
{
|
||||
m_data.try_remove(key_string);
|
||||
check(TRY(m_data.try_set(key_string, value_string)));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> ConfigFile::write_number(StringView key, int value)
|
||||
{
|
||||
auto value_string = TRY(String::format("%d"_sv, value));
|
||||
|
||||
return write_string(key, value_string.view());
|
||||
}
|
||||
|
||||
Result<void> ConfigFile::write_boolean(StringView key, bool value)
|
||||
{
|
||||
StringView value_string = value ? "true" : "false";
|
||||
|
||||
return write_string(key, value_string);
|
||||
}
|
||||
|
||||
Result<void> ConfigFile::sync()
|
||||
{
|
||||
auto file = TRY(os::File::open(m_path, os::File::WriteOnly));
|
||||
|
||||
for (auto& pair : m_data)
|
||||
{
|
||||
file->write_formatted("%s=%s\n", pair.key.chars(), pair.value.release_value().chars());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
143
system/init.cpp
143
system/init.cpp
@ -6,6 +6,7 @@
|
||||
#include <luna/Utf8.h>
|
||||
#include <luna/Vector.h>
|
||||
#include <os/ArgumentParser.h>
|
||||
#include <os/Config.h>
|
||||
#include <os/Directory.h>
|
||||
#include <os/File.h>
|
||||
#include <os/IPC.h>
|
||||
@ -191,129 +192,49 @@ static Result<void> load_service(const os::Path& path)
|
||||
{
|
||||
do_log("[init] reading service file: %s\n", path.name().chars());
|
||||
|
||||
auto file = TRY(os::File::open(path, os::File::ReadOnly));
|
||||
auto file = TRY(os::ConfigFile::open(path));
|
||||
|
||||
Service service;
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto line = TRY(file->read_line());
|
||||
if (line.is_empty()) break;
|
||||
|
||||
line.trim("\n");
|
||||
if (line.is_empty()) continue;
|
||||
|
||||
auto parts = TRY(line.split_once('='));
|
||||
if (parts.size() < 2 || parts[0].is_empty() || parts[1].is_empty())
|
||||
{
|
||||
do_log("[init] file contains invalid line, aborting: '%s'\n", line.chars());
|
||||
return {};
|
||||
}
|
||||
|
||||
if (parts[0].view() == "Name")
|
||||
{
|
||||
service.name = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "Description")
|
||||
{
|
||||
// We let users specify this in the config file, but init doesn't actually use it.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "Command")
|
||||
{
|
||||
service.command = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "Restart")
|
||||
{
|
||||
if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1)
|
||||
{
|
||||
service.restart = true;
|
||||
continue;
|
||||
}
|
||||
service.restart = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "Environment")
|
||||
{
|
||||
service.environment = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "StandardOutput")
|
||||
{
|
||||
service.standard_output = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "StandardError")
|
||||
{
|
||||
service.standard_error = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "StandardInput")
|
||||
{
|
||||
service.standard_input = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "WorkingDirectory")
|
||||
{
|
||||
service.working_directory = move(parts[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_is_system && parts[0].view() == "User")
|
||||
{
|
||||
auto* pw = getpwnam(parts[1].chars());
|
||||
if (!pw) continue;
|
||||
service.user = pw->pw_uid;
|
||||
service.group = pw->pw_gid;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "Wait")
|
||||
{
|
||||
if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1)
|
||||
{
|
||||
service.wait = true;
|
||||
continue;
|
||||
}
|
||||
service.wait = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parts[0].view() == "WaitUntilReady")
|
||||
{
|
||||
if (parts[1].view() == "true" || parts[1].view().to_uint().value_or(0) == 1)
|
||||
{
|
||||
service.wait_notify = true;
|
||||
continue;
|
||||
}
|
||||
service.wait_notify = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
do_log("[init] skipping unknown entry name %s\n", parts[0].chars());
|
||||
}
|
||||
|
||||
if (service.name.is_empty())
|
||||
auto name = file->read_string("Name");
|
||||
if (!name.has_value())
|
||||
{
|
||||
do_log("[init] service file is missing 'Name' entry, aborting!\n");
|
||||
return {};
|
||||
}
|
||||
service.name = TRY(String::from_string_view(name.value()));
|
||||
|
||||
if (service.command.is_empty())
|
||||
auto command = file->read_string("Command");
|
||||
if (!command.has_value())
|
||||
{
|
||||
do_log("[init] service file is missing 'Command' entry, aborting!\n");
|
||||
return {};
|
||||
}
|
||||
service.command = TRY(String::from_string_view(command.value()));
|
||||
|
||||
service.restart = file->read_boolean_or("Restart", false);
|
||||
service.environment = TRY(String::from_string_view(file->read_string_or("Environment", {})));
|
||||
service.standard_output = TRY(String::from_string_view(file->read_string_or("StandardOutput", {})));
|
||||
service.standard_error = TRY(String::from_string_view(file->read_string_or("StandardError", {})));
|
||||
service.standard_input = TRY(String::from_string_view(file->read_string_or("StandardInput", {})));
|
||||
service.working_directory = TRY(String::from_string_view(file->read_string_or("WorkingDirectory", {})));
|
||||
|
||||
if (g_is_system)
|
||||
{
|
||||
auto user = file->read_string("User");
|
||||
if (user.has_value())
|
||||
{
|
||||
auto* pw = getpwnam(user.value().chars());
|
||||
if (pw)
|
||||
{
|
||||
service.user = pw->pw_uid;
|
||||
service.group = pw->pw_gid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
service.wait = file->read_boolean_or("Wait", false);
|
||||
service.wait_notify = file->read_boolean_or("WaitUntilReady", false);
|
||||
|
||||
do_log("[init] loaded service %s into memory\n", service.name.chars());
|
||||
|
||||
|
@ -64,7 +64,7 @@ make install-gcc
|
||||
make install-target-libgcc
|
||||
|
||||
mkdir -p $LUNA_BUILD_DIR
|
||||
cmake -S $LUNA_ROOT -B $LUNA_BUILD_DIR -G "$LUNA_CMAKE_GENERATOR_NAME"
|
||||
cmake -S $LUNA_ROOT -B $LUNA_BUILD_DIR -G "$LUNA_CMAKE_GENERATOR_NAME" -DLIBC_BOOTSTRAP=1
|
||||
cmake --build $LUNA_BUILD_DIR --target libc
|
||||
|
||||
make all-target-libstdc++-v3 CXXFLAGS_FOR_TARGET="-fno-exceptions" -j$(nproc)
|
||||
|
Loading…
Reference in New Issue
Block a user