2023-08-16 18:02:54 +00:00
|
|
|
#define CLIENT_IMPLEMENTATION
|
2023-08-14 16:15:29 +00:00
|
|
|
#include "Client.h"
|
|
|
|
#include "IPC.h"
|
2023-09-16 09:45:19 +00:00
|
|
|
#include "Keyboard.h"
|
2023-08-03 10:20:59 +00:00
|
|
|
#include "Mouse.h"
|
|
|
|
#include "Screen.h"
|
2023-08-03 15:38:49 +00:00
|
|
|
#include "Window.h"
|
2023-08-03 10:20:59 +00:00
|
|
|
#include <errno.h>
|
|
|
|
#include <moon/Keyboard.h>
|
|
|
|
#include <os/ArgumentParser.h>
|
|
|
|
#include <os/File.h>
|
2023-08-03 14:40:17 +00:00
|
|
|
#include <os/LocalServer.h>
|
2023-08-07 20:51:28 +00:00
|
|
|
#include <os/Process.h>
|
2023-08-14 09:07:19 +00:00
|
|
|
#include <os/Security.h>
|
2023-08-03 10:20:59 +00:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/poll.h>
|
2023-08-06 10:45:13 +00:00
|
|
|
#include <time.h>
|
2023-08-03 10:20:59 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2023-08-16 18:02:54 +00:00
|
|
|
static void debug(const Vector<OwnedPtr<Client>>& clients)
|
2023-08-16 14:48:55 +00:00
|
|
|
{
|
|
|
|
os::println("--- wind: DEBUG OUTPUT ---");
|
|
|
|
|
|
|
|
os::println("-- wind: Listing clients --");
|
|
|
|
|
|
|
|
for (const auto& client : clients)
|
|
|
|
{
|
2023-08-16 18:02:54 +00:00
|
|
|
os::println("Client with fd %d, owns %zu windows", client->conn.fd(), client->windows.size());
|
2023-08-16 14:48:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
os::println("-- wind: Listing windows --");
|
|
|
|
|
|
|
|
for (const auto& window : g_windows)
|
|
|
|
{
|
|
|
|
os::println("Window of client (fd %d), id %d, %sdecorated, %sdirty (\"%s\") (%d,%d,%d,%d)",
|
|
|
|
window->client->conn.fd(), window->id, window->decorated ? "" : "not ", window->dirty ? "" : "not ",
|
|
|
|
window->name.chars(), window->surface.pos.x, window->surface.pos.y, window->surface.width,
|
|
|
|
window->surface.height);
|
|
|
|
}
|
|
|
|
|
|
|
|
os::println("-- wind: Listing processes --");
|
|
|
|
|
|
|
|
system("ps");
|
|
|
|
|
2023-08-17 18:22:22 +00:00
|
|
|
os::println("-- wind: Listing memory usage --");
|
|
|
|
|
|
|
|
system("free -h");
|
|
|
|
|
2023-08-16 14:48:55 +00:00
|
|
|
os::println("--- wind: END DEBUG OUTPUT ---");
|
|
|
|
}
|
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
Result<int> luna_main(int argc, char** argv)
|
|
|
|
{
|
2023-08-06 10:45:13 +00:00
|
|
|
srand((unsigned)time(NULL));
|
|
|
|
|
2023-08-22 11:37:07 +00:00
|
|
|
TRY(os::Security::pledge("stdio rpath wpath cpath unix proc exec tty id", NULL));
|
2023-08-14 09:07:19 +00:00
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
StringView socket_path = "/tmp/wind.sock";
|
|
|
|
StringView user;
|
|
|
|
|
|
|
|
os::ArgumentParser parser;
|
|
|
|
parser.add_description("The display server for Luna's graphical user interface."_sv);
|
|
|
|
parser.add_system_program_info("wind"_sv);
|
|
|
|
parser.add_value_argument(socket_path, 's', "socket"_sv, "the path for the local IPC socket"_sv);
|
|
|
|
parser.add_value_argument(user, 'u', "user"_sv, "the user to run as"_sv);
|
|
|
|
parser.parse(argc, argv);
|
|
|
|
|
|
|
|
if (geteuid() != 0)
|
|
|
|
{
|
|
|
|
os::eprintln("error: wind must be run as root to initialize resources, run with --user=<USERNAME> to drop "
|
|
|
|
"privileges afterwards");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-08-31 12:55:40 +00:00
|
|
|
if (!isatty(STDIN_FILENO))
|
|
|
|
{
|
|
|
|
os::eprintln("error: wind must be run from a TTY!");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
auto mouse = TRY(os::File::open("/dev/mouse", os::File::ReadOnly));
|
|
|
|
mouse->set_buffer(os::File::NotBuffered);
|
|
|
|
mouse->set_close_on_exec();
|
|
|
|
|
|
|
|
auto keyboard = TRY(os::File::open("/dev/kbd", os::File::ReadOnly));
|
|
|
|
keyboard->set_buffer(os::File::NotBuffered);
|
|
|
|
keyboard->set_close_on_exec();
|
|
|
|
|
2023-08-15 10:56:55 +00:00
|
|
|
TRY(Screen::open());
|
|
|
|
auto& screen = Screen::the();
|
2023-08-03 10:20:59 +00:00
|
|
|
|
|
|
|
Mouse mouse_pointer { screen.canvas() };
|
|
|
|
|
|
|
|
ioctl(STDIN_FILENO, TTYSETGFX, 1);
|
|
|
|
|
|
|
|
setpgid(0, 0);
|
|
|
|
|
|
|
|
int fd = open("/dev/null", O_RDONLY);
|
|
|
|
if (fd >= 0)
|
|
|
|
{
|
|
|
|
dup2(fd, STDIN_FILENO);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
clearenv();
|
|
|
|
|
|
|
|
if (!user.is_empty())
|
|
|
|
{
|
|
|
|
auto* pwd = getpwnam(user.chars());
|
|
|
|
if (pwd)
|
|
|
|
{
|
|
|
|
setgid(pwd->pw_gid);
|
|
|
|
setuid(pwd->pw_uid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-07 20:51:28 +00:00
|
|
|
auto server = TRY(os::LocalServer::create(socket_path, false));
|
|
|
|
TRY(server->listen(20));
|
|
|
|
|
2023-08-14 09:07:19 +00:00
|
|
|
StringView args[] = { "/usr/bin/init"_sv, "--user"_sv };
|
|
|
|
TRY(os::Process::spawn("/usr/bin/init"_sv, Slice<StringView> { args, 2 }, false));
|
2023-08-07 20:51:28 +00:00
|
|
|
|
2023-09-14 20:51:19 +00:00
|
|
|
ui::Color background = ui::Color::from_rgb(0x10, 0x10, 0x10);
|
2023-08-03 10:20:59 +00:00
|
|
|
|
2023-08-16 18:02:54 +00:00
|
|
|
Vector<OwnedPtr<Client>> clients;
|
2023-08-14 11:24:26 +00:00
|
|
|
Vector<struct pollfd> fds;
|
|
|
|
TRY(fds.try_append({ .fd = mouse->fd(), .events = POLLIN, .revents = 0 }));
|
|
|
|
TRY(fds.try_append({ .fd = keyboard->fd(), .events = POLLIN, .revents = 0 }));
|
|
|
|
TRY(fds.try_append({ .fd = server->fd(), .events = POLLIN, .revents = 0 }));
|
2023-08-03 14:40:17 +00:00
|
|
|
|
2023-08-22 11:37:07 +00:00
|
|
|
TRY(os::Security::pledge("stdio rpath wpath cpath unix proc exec", NULL));
|
2023-08-14 09:07:19 +00:00
|
|
|
|
2023-08-03 10:20:59 +00:00
|
|
|
while (1)
|
|
|
|
{
|
2023-08-03 15:38:49 +00:00
|
|
|
screen.canvas().fill(background);
|
|
|
|
for (auto* window : g_windows) window->draw(screen.canvas());
|
|
|
|
mouse_pointer.draw(screen.canvas());
|
|
|
|
screen.sync();
|
|
|
|
|
2023-08-14 11:24:26 +00:00
|
|
|
for (auto& pfd : fds) { pfd.revents = 0; }
|
2023-08-03 10:20:59 +00:00
|
|
|
|
2023-08-14 11:24:26 +00:00
|
|
|
int rc = poll(fds.data(), fds.size(), 1000);
|
2023-08-03 10:20:59 +00:00
|
|
|
if (!rc) continue;
|
2023-08-07 20:51:28 +00:00
|
|
|
if (rc < 0 && errno != EINTR) { os::println("poll: error: %s", strerror(errno)); }
|
2023-08-03 10:20:59 +00:00
|
|
|
|
|
|
|
if (fds[0].revents & POLLIN)
|
|
|
|
{
|
|
|
|
moon::MousePacket packet;
|
|
|
|
TRY(mouse->read_typed(packet));
|
2023-08-03 15:38:49 +00:00
|
|
|
mouse_pointer.update(packet);
|
2023-08-03 10:20:59 +00:00
|
|
|
}
|
|
|
|
if (fds[1].revents & POLLIN)
|
|
|
|
{
|
|
|
|
moon::KeyboardPacket packet;
|
|
|
|
TRY(keyboard->read_typed(packet));
|
2023-08-16 14:48:55 +00:00
|
|
|
if (!packet.released && packet.key == moon::K_Tab) debug(clients);
|
2023-09-16 09:45:19 +00:00
|
|
|
auto request = wind::Keyboard::decode_keyboard_event((moon::KeyCode)packet.key, packet.released);
|
|
|
|
if (g_windows.last().has_value())
|
|
|
|
{
|
|
|
|
auto* window = g_windows.last().value();
|
|
|
|
request.window = window->id;
|
|
|
|
os::IPC::send_async(window->client->conn, request);
|
|
|
|
}
|
2023-08-03 10:20:59 +00:00
|
|
|
}
|
2023-08-14 11:24:26 +00:00
|
|
|
for (usize i = 0; i < clients.size(); i++)
|
|
|
|
{
|
2023-08-16 18:02:54 +00:00
|
|
|
if (fds[i + 3].revents & POLLIN) wind::handle_ipc(*clients[i]);
|
2023-08-14 11:24:26 +00:00
|
|
|
if (fds[i + 3].revents & POLLHUP)
|
|
|
|
{
|
|
|
|
os::println("wind: Client %d disconnected", i);
|
|
|
|
fds.remove_at(i + 3);
|
|
|
|
auto client = clients.remove_at(i);
|
2023-08-16 18:02:54 +00:00
|
|
|
client->conn.disconnect();
|
|
|
|
for (auto& window : client->windows)
|
2023-08-14 16:15:29 +00:00
|
|
|
{
|
2023-08-15 09:20:17 +00:00
|
|
|
if (window)
|
|
|
|
{
|
|
|
|
g_windows.remove(window);
|
2023-09-16 09:45:51 +00:00
|
|
|
mouse_pointer.window_did_close(window);
|
2023-08-15 09:20:17 +00:00
|
|
|
delete window;
|
|
|
|
}
|
2023-08-14 16:15:29 +00:00
|
|
|
}
|
2023-08-14 11:24:26 +00:00
|
|
|
}
|
|
|
|
}
|
2023-08-03 14:40:17 +00:00
|
|
|
if (fds[2].revents & POLLIN)
|
|
|
|
{
|
|
|
|
auto client = TRY(server->accept());
|
|
|
|
os::println("wind: New client connected!");
|
2023-08-14 11:24:26 +00:00
|
|
|
TRY(fds.try_append({ .fd = client.fd(), .events = POLLIN, .revents = 0 }));
|
2023-08-16 18:02:54 +00:00
|
|
|
OwnedPtr<Client> c = TRY(adopt_owned_if_nonnull(new Client(move(client))));
|
2023-08-14 16:15:29 +00:00
|
|
|
TRY(clients.try_append(move(c)));
|
2023-08-03 14:40:17 +00:00
|
|
|
}
|
2023-08-03 10:20:59 +00:00
|
|
|
}
|
|
|
|
}
|