Luna/apps/launch.cpp
apio 7d69ac56e2
All checks were successful
Build and test / build (push) Successful in 1m41s
apps+libos+shell+wind: Correct a bunch of format strings
2024-03-29 14:42:38 +01:00

106 lines
3.1 KiB
C++

/**
* @file launch.cpp
* @author apio (cloudapio.eu)
* @brief Background process that handles detached launching of apps.
*
* @copyright Copyright (c) 2024, the Luna authors.
*
*/
#include <errno.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <os/LocalServer.h>
#include <os/Process.h>
#include <os/Security.h>
#include <os/ipc/Launcher.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
Result<void> handle_launch_detached_message(os::IPC::ClientConnection& client)
{
os::Launcher::LaunchDetachedRequest request;
if (!TRY(client.read_message(request))) return {};
auto path = COPY_IPC_STRING(request.command);
StringView args[] = { path.view() };
os::Process::spawn(args[0], { args, 1 }, request.search_in_path);
return {};
}
void handle_ipc_message(os::IPC::ClientConnection& client, u8 id, void*)
{
switch (id)
{
case os::Launcher::LAUNCH_DETACHED_ID: handle_launch_detached_message(client); break;
default: os::eprintln("launch: Invalid IPC message from client!"); return;
}
}
void sigchld_handler(int)
{
os::Process::wait(os::Process::ANY_CHILD, nullptr);
}
Result<int> luna_main(int argc, char** argv)
{
TRY(os::Security::pledge("stdio wpath cpath unix proc exec", NULL));
StringView socket_path = "/tmp/launch.sock";
os::ArgumentParser parser;
parser.add_description("Background process that handles detached launching of apps."_sv);
parser.add_system_program_info("launch"_sv);
parser.parse(argc, argv);
signal(SIGCHLD, sigchld_handler);
auto server = TRY(os::LocalServer::create(socket_path, false));
TRY(server->listen(20));
Vector<OwnedPtr<os::IPC::ClientConnection>> clients;
Vector<struct pollfd> fds;
TRY(fds.try_append({ .fd = server->fd(), .events = POLLIN, .revents = 0 }));
TRY(os::Security::pledge("stdio unix proc exec", NULL));
while (1)
{
for (auto& pfd : fds) { pfd.revents = 0; }
int rc = poll(fds.data(), fds.size(), 1000);
if (!rc) continue;
if (rc < 0 && errno != EINTR) { os::println("poll: error: %s", strerror(errno)); }
if (fds[0].revents & POLLIN)
{
auto client = TRY(server->accept());
os::println("launch: New client connected!");
TRY(fds.try_append({ .fd = client.fd(), .events = POLLIN, .revents = 0 }));
auto connection = TRY(os::IPC::ClientConnection::adopt_connection(move(client)));
connection->set_message_handler(handle_ipc_message, nullptr);
TRY(clients.try_append(move(connection)));
}
for (usize i = 0; i < clients.size(); i++)
{
if (fds[i + 1].revents & POLLIN) clients[i]->check_for_messages();
if (fds[i + 1].revents & POLLHUP)
{
os::println("launch: Client %zu disconnected", i);
fds.remove_at(i + 1);
auto client = clients.remove_at(i);
client->disconnect();
}
}
}
}