106 lines
3.1 KiB
C++
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();
|
|
}
|
|
}
|
|
}
|
|
}
|