/** * @file launch.cpp * @author apio (cloudapio.eu) * @brief Background process that handles detached launching of apps. * * @copyright Copyright (c) 2024, the Luna authors. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Result 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 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)); // We're ready now. os::IPC::notify_parent(); Vector> clients; Vector 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(); } } } }