init: Use pledge and support init --user

This commit is contained in:
apio 2023-08-14 10:46:28 +02:00
parent 9954fc1658
commit cfb60fad25
Signed by: apio
GPG Key ID: B8A7D06E42258954

View File

@ -4,9 +4,11 @@
#include <luna/Sort.h>
#include <luna/String.h>
#include <luna/Vector.h>
#include <os/ArgumentParser.h>
#include <os/Directory.h>
#include <os/File.h>
#include <os/Process.h>
#include <os/Security.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@ -247,9 +249,9 @@ static Result<void> load_service(const os::Path& path)
return {};
}
static Result<void> load_services()
static Result<void> load_services(StringView path)
{
auto dir = TRY(os::Directory::open("/etc/init"));
auto dir = TRY(os::Directory::open(path));
auto services = TRY(dir->list_names(os::Directory::Filter::ParentAndBase));
sort(services.begin(), services.end(), String::compare);
@ -259,9 +261,9 @@ static Result<void> load_services()
return {};
}
static Result<void> start_services()
static Result<void> start_services(StringView path)
{
TRY(load_services());
TRY(load_services(path));
for (auto& service : g_services)
{
do_log("[init] starting service %s\n", service.name.chars());
@ -301,7 +303,7 @@ static void mount_shmfs()
if (chmod("/dev/shm", 01777) < 0) exit(255);
}
int main()
Result<int> sysinit()
{
if (getpid() != 1)
{
@ -315,6 +317,8 @@ int main()
stdout = fopen("/dev/console", "w");
stderr = fopen("/dev/console", "w");
TRY(os::Security::pledge("stdio rpath wpath cpath fattr host mount proc exec signal", nullptr));
mount_tmpfs();
mount_shmfs();
@ -330,7 +334,11 @@ int main()
if (signal(SIGTERM, sigterm_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGTERM\n");
if (signal(SIGQUIT, sigquit_handler) == SIG_ERR) do_log("[init] failed to register handler for SIGQUIT\n");
start_services();
TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr));
start_services("/etc/init");
TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr));
while (1)
{
@ -365,3 +373,66 @@ int main()
}
}
}
Result<int> user_init()
{
setpgid(0, 0);
g_init_log = fopen("/dev/uart0", "w");
check(g_init_log);
setlinebuf(g_init_log);
fcntl(fileno(g_init_log), F_SETFD, FD_CLOEXEC);
TRY(os::Security::pledge("stdio rpath wpath cpath proc exec", nullptr));
start_services("/etc/user");
TRY(os::Security::pledge("stdio rpath wpath proc exec", nullptr));
while (1)
{
int status;
auto rc = os::Process::wait(os::Process::ANY_CHILD, &status);
if (rc.has_error()) continue;
pid_t child = rc.release_value();
for (auto& service : g_services)
{
if (service.pid.has_value() && service.pid.value() == child)
{
if (WIFEXITED(status))
{
do_log("[init] service %s exited with status %d\n", service.name.chars(), WEXITSTATUS(status));
}
else
{
do_log("[init] service %s was terminated by signal %d\n", service.name.chars(), WTERMSIG(status));
}
if (service.restart)
{
do_log("[init] restarting service %s\n", service.name.chars());
start_service(service);
}
break;
}
}
}
}
Result<int> luna_main(int argc, char** argv)
{
bool user;
os::ArgumentParser parser;
parser.add_description("The init system for Luna.");
parser.add_system_program_info("init"_sv);
parser.add_switch_argument(user, 'u', "user"_sv, "initialize a user session instead of the system");
parser.parse(argc, argv);
if (user) return user_init();
return sysinit();
}