Compare commits

..

10 Commits

Author SHA1 Message Date
8a71861470
Remove the build status badge
Some checks are pending
Build and test / build (push) Waiting to run
It links to drone, which we have phased out in favor of Gitea Actions.
2024-03-29 20:42:09 +01:00
ade1e60eb5
editor: Fix creation of new files
Some checks are pending
Build and test / build (push) Waiting to run
The editor is supposed to create files if they don't exist, however before this commit stat() would fail and exit load_file() before we even got to File::open_or_create().
2024-03-29 20:41:16 +01:00
662a315597
editor: Display only the basename of the current file in the window title 2024-03-29 20:36:44 +01:00
6c8a4ad995
terminal: Use widget->window() instead of the App's main window 2024-03-29 20:18:59 +01:00
8db14d8883
editor: Use TextInput as a base class 2024-03-29 20:18:58 +01:00
fbc91bfe8c
libui: Add a TextInput base class to handle most input fields and add an InputField class for single-line inputs 2024-03-29 20:18:58 +01:00
2aa0612400
editor: Refuse to load non-regular file types
All checks were successful
Build and test / build (push) Successful in 2m4s
2024-03-14 13:09:03 +01:00
fc17399d82
editor: Remove insert mode and use the arrow keys to navigate, plus Ctrl+S to save
All checks were successful
Build and test / build (push) Successful in 2m4s
2024-03-14 12:40:46 +01:00
aae5f21f7f
editor: Add basic loading and saving 2024-03-14 12:40:46 +01:00
d996e3f9f8
editor: Add a basic text editor 2024-03-14 12:40:46 +01:00
17 changed files with 88 additions and 267 deletions

View File

@ -38,11 +38,17 @@ Additionally, the build process needs some extra dependencies to run: `cmake`, `
`tools/run.sh` is the script you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU. `tools/run.sh` is the script you should use in most cases. It will build changed files, install, make an ISO image, and run Luna in QEMU.
If you have no toolchain set up, `run.sh` will build it automatically, which means that you don't necessarily have to run `setup.sh` manually since `run.sh` does it for you. If you have no toolchain set up, `run.sh` will build it automatically, which means that you don't necessarily have to run `setup.sh` since `run.sh` does it for you.
## Prebuilt images ## Prebuilt images
Prebuilt ISO images for every release version can be found at [pub.cloudapio.eu](https://pub.cloudapio.eu/luna/releases). Prebuilt ISO images (numbered) for every version can be found at [pub.cloudapio.eu](https://pub.cloudapio.eu/luna/releases).
These images are built manually whenever a new release is created, and thus don't reflect the latest changes on the `main` branch.
Every hour, this server pulls the latest commits on `main` and builds an hourly ISO image. The ten most recent ones can be found in the [hourly](https://pub.cloudapio.eu/luna/hourly) directory, and [Luna-latest.iso](https://pub.cloudapio.eu/luna/Luna-latest.iso) should always be symlinked to the newest one.
These images do reflect the latest changes on the `main` branch, but are obviously less stable. Additionally, an hourly image will be skipped if building the latest commit of the project fails.
## Is there third-party software I can use on Luna? ## Is there third-party software I can use on Luna?

View File

@ -51,4 +51,3 @@ luna_app(clock.cpp clock)
target_link_libraries(clock PUBLIC ui) target_link_libraries(clock PUBLIC ui)
luna_app(startui.cpp startui) luna_app(startui.cpp startui)
luna_app(launch.cpp launch) luna_app(launch.cpp launch)
luna_app(run.cpp run)

View File

@ -31,7 +31,7 @@ Result<void> handle_launch_detached_message(os::IPC::ClientConnection& client)
StringView args[] = { path.view() }; StringView args[] = { path.view() };
os::Process::spawn(args[0], { args, 1 }, request.search_in_path); os::Process::spawn(args[0], { args, 1 }, false);
return {}; return {};
} }
@ -95,7 +95,7 @@ Result<int> luna_main(int argc, char** argv)
if (fds[i + 1].revents & POLLIN) clients[i]->check_for_messages(); if (fds[i + 1].revents & POLLIN) clients[i]->check_for_messages();
if (fds[i + 1].revents & POLLHUP) if (fds[i + 1].revents & POLLHUP)
{ {
os::println("launch: Client %zu disconnected", i); os::println("launch: Client %d disconnected", i);
fds.remove_at(i + 1); fds.remove_at(i + 1);
auto client = clients.remove_at(i); auto client = clients.remove_at(i);
client->disconnect(); client->disconnect();

View File

@ -212,15 +212,14 @@ Result<int> luna_main(int argc, char** argv)
{ {
if (colors) if (colors)
{ {
os::println("%s %lu %4s %4s %10lu %s%s" RESET_COLORS "%s" SYMLINK_COLOR "%s" RESET_COLORS, os::println("%s %u %4s %4s %10lu %s%s" RESET_COLORS "%s" SYMLINK_COLOR "%s" RESET_COLORS,
formatted_mode, st.st_nlink, owner.chars(), group.chars(), st.st_size, formatted_mode, st.st_nlink, owner.chars(), group.chars(), st.st_size,
file_type_color(file), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars()); file_type_color(file), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars());
} }
else else
{ {
os::println("%s %lu %4s %4s %10lu %s%s%s", formatted_mode, st.st_nlink, owner.chars(), os::println("%s %u %4s %4s %10lu %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(),
group.chars(), st.st_size, file.name.chars(), link.is_empty() ? "" : " -> ", st.st_size, file.name.chars(), link.is_empty() ? "" : " -> ", link.chars());
link.chars());
} }
} }
else else
@ -228,13 +227,13 @@ Result<int> luna_main(int argc, char** argv)
auto size = TRY(to_dynamic_unit(st.st_size, 10, false, si ? Unit::SI : Unit::Binary, false)); auto size = TRY(to_dynamic_unit(st.st_size, 10, false, si ? Unit::SI : Unit::Binary, false));
if (colors) if (colors)
{ {
os::println("%s %lu %4s %4s %6s %s%s" RESET_COLORS "%s" SYMLINK_COLOR "%s" RESET_COLORS, os::println("%s %u %4s %4s %6s %s%s" RESET_COLORS "%s" SYMLINK_COLOR "%s" RESET_COLORS,
formatted_mode, st.st_nlink, owner.chars(), group.chars(), size.chars(), formatted_mode, st.st_nlink, owner.chars(), group.chars(), size.chars(),
file_type_color(file), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars()); file_type_color(file), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars());
} }
else else
{ {
os::println("%s %lu %4s %4s %6s %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(), os::println("%s %u %4s %4s %6s %s%s%s", formatted_mode, st.st_nlink, owner.chars(), group.chars(),
size.chars(), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars()); size.chars(), file.name.chars(), link.is_empty() ? "" : " -> ", link.chars());
} }
} }

View File

@ -34,7 +34,7 @@ Result<int> luna_main(int argc, char** argv)
close(fd); close(fd);
} }
os::println("%s", str.chars()); os::println("%s"_sv, str.chars());
return 0; return 0;
} }

View File

@ -1,35 +0,0 @@
/**
* @file run.cpp
* @author apio (cloudapio.eu)
* @brief Tiny command-line utility to start a detached program in the current GUI session.
*
* @copyright Copyright (c) 2024, the Luna authors.
*
*/
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <os/LocalClient.h>
#include <os/ipc/Launcher.h>
Result<int> luna_main(int argc, char** argv)
{
StringView program;
os::ArgumentParser parser;
parser.add_description("Start a detached program in the current GUI session."_sv);
parser.add_system_program_info("run"_sv);
parser.add_positional_argument(program, "program", true);
parser.parse(argc, argv);
OwnedPtr<os::IPC::Client> launcher_client = TRY(os::IPC::Client::connect("/tmp/launch.sock", false));
os::println("Requesting to start program '%s'...", program.chars());
os::Launcher::LaunchDetachedRequest request;
SET_IPC_STRING(request.command, program.chars());
request.search_in_path = true;
launcher_client->send_async(request);
return 0;
}

View File

@ -33,7 +33,7 @@ Result<int> luna_main(int argc, char** argv)
auto cmdline = TRY(String::join(command, " ")); auto cmdline = TRY(String::join(command, " "));
os::println("%s %ld.%.2lds user %ld.%.2lds system", cmdline.chars(), usage.ru_utime.tv_sec, os::println("%s %d.%.2ds user %d.%.2ds system"_sv, cmdline.chars(), usage.ru_utime.tv_sec,
usage.ru_utime.tv_usec / 10000, usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 10000); usage.ru_utime.tv_usec / 10000, usage.ru_stime.tv_sec, usage.ru_stime.tv_usec / 10000);
return 0; return 0;

View File

@ -6,7 +6,6 @@
#include <luna/Format.h> #include <luna/Format.h>
#include <luna/SourceLocation.h> #include <luna/SourceLocation.h>
#include <luna/Spinlock.h> #include <luna/Spinlock.h>
#include <luna/StringBuilder.h>
static bool g_debug_enabled = true; static bool g_debug_enabled = true;
static bool g_serial_enabled = true; static bool g_serial_enabled = true;
@ -175,23 +174,3 @@ static bool g_check_already_failed = false;
} }
CPU::efficient_halt(); CPU::efficient_halt();
} }
Result<void> hexdump(void* data, usize size)
{
StringBuilder sb;
u8* ptr = (u8*)data;
while (size)
{
TRY(sb.format("%#2x ", *ptr));
ptr++;
size--;
}
auto message = TRY(sb.string());
kdbgln("hexdump: %s", message.chars());
return {};
}

View File

@ -26,8 +26,6 @@ void set_text_console_initialized();
#define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__) #define kwarnln(...) log(LogLevel::Warn, __VA_ARGS__)
#define kerrorln(...) log(LogLevel::Error, __VA_ARGS__) #define kerrorln(...) log(LogLevel::Error, __VA_ARGS__)
Result<void> hexdump(void* data, usize size);
[[noreturn]] extern void __critical_error_handler(SourceLocation location, const char* expr, const char* failmsg, [[noreturn]] extern void __critical_error_handler(SourceLocation location, const char* expr, const char* failmsg,
const char* errmsg); const char* errmsg);

View File

@ -157,27 +157,13 @@ namespace ATA
void Channel::select(u8 drive) void Channel::select(u8 drive)
{ {
if (drive == m_current_drive) return;
u8 value = (u8)(drive << 4) | 0xa0; u8 value = (u8)(drive << 4) | 0xa0;
if (value == m_current_select_value) return;
write_register(Register::DriveSelect, value); write_register(Register::DriveSelect, value);
delay_400ns(); delay_400ns();
m_current_select_value = value;
m_current_drive = drive;
}
void Channel::select(u8 base, u8 drive)
{
u8 value = (u8)(drive << 4) | base;
if (value == m_current_select_value) return;
write_register(Register::DriveSelect, value);
delay_400ns();
m_current_select_value = value;
m_current_drive = drive; m_current_drive = drive;
} }
@ -557,61 +543,10 @@ namespace ATA
return true; return true;
} }
void Drive::select_lba(u64 lba, usize count) Result<void> Drive::send_packet_atapi_pio(const atapi_packet* packet, void* out, u16 response_size)
{
if (m_is_lba48)
{
m_channel->write_register(Register::SectorCount, (u8)((count >> 8) & 0xff));
m_channel->write_register(Register::LBALow, (u8)((lba >> 24) & 0xff));
m_channel->write_register(Register::LBAMiddle, (u8)((lba >> 32) & 0xff));
m_channel->write_register(Register::LBAHigh, (u8)((lba >> 40) & 0xff));
}
m_channel->write_register(Register::SectorCount, (u8)(count & 0xff));
m_channel->write_register(Register::LBALow, (u8)(lba & 0xff));
m_channel->write_register(Register::LBAMiddle, (u8)((lba >> 8) & 0xff));
m_channel->write_register(Register::LBAHigh, (u8)((lba >> 16) & 0xff));
}
Result<void> Drive::read_pio_bytes(void* out, usize size)
{ {
u8* ptr = (u8*)out; u8* ptr = (u8*)out;
usize i = 0;
while (i < size)
{
TRY(m_channel->wait_until_ready());
usize byte_count;
if (m_is_atapi)
{
byte_count =
m_channel->read_register(Register::LBAHigh) << 8 | m_channel->read_register(Register::LBAMiddle);
}
else
byte_count = min(512ul, size - i);
usize word_count = byte_count / 2;
while (word_count--)
{
u16 value = m_channel->read_data();
ptr[0] = (u8)(value & 0xff);
ptr[1] = (u8)(value >> 8);
ptr += 2;
}
i += byte_count;
m_channel->delay_400ns();
}
return {};
}
Result<void> Drive::send_packet_atapi_pio(const atapi_packet* packet, void* out, u16 response_size)
{
m_channel->select(m_drive_index); m_channel->select(m_drive_index);
// We use PIO here. // We use PIO here.
@ -624,11 +559,30 @@ namespace ATA
m_channel->delay_400ns(); m_channel->delay_400ns();
usize i = 0;
TRY(m_channel->wait_until_ready()); TRY(m_channel->wait_until_ready());
for (int j = 0; j < 6; j++) m_channel->write_data(packet->command_words[j]); for (int j = 0; j < 6; j++) m_channel->write_data(packet->command_words[j]);
TRY(read_pio_bytes(out, response_size)); while (i < response_size)
{
TRY(m_channel->wait_until_ready());
usize byte_count =
m_channel->read_register(Register::LBAHigh) << 8 | m_channel->read_register(Register::LBAMiddle);
usize word_count = byte_count / 2;
while (word_count--)
{
u16 value = m_channel->read_data();
ptr[0] = (u8)(value & 0xff);
ptr[1] = (u8)(value >> 8);
ptr += 2;
}
i += byte_count;
}
return {}; return {};
} }
@ -750,26 +704,6 @@ namespace ATA
return send_packet_atapi_pio(&read_packet, out, (u16)size); return send_packet_atapi_pio(&read_packet, out, (u16)size);
} }
Result<void> Drive::ata_read_pio(u64 lba, void* out, usize size)
{
check(lba < m_block_count);
check(size <= ARCH_PAGE_SIZE);
usize count = ceil_div(size, m_block_size);
m_channel->select(m_is_lba48 ? 0x40 : (0xe0 | ((lba >> 24) & 0xf)), m_drive_index);
select_lba(lba, count);
m_channel->write_register(Register::Command, m_is_lba48 ? CMD_ReadSectorsExt : CMD_ReadSectors);
m_channel->delay_400ns();
TRY(read_pio_bytes(out, size));
return {};
}
Result<void> Drive::read_lba(u64 lba, void* out, usize nblocks) Result<void> Drive::read_lba(u64 lba, void* out, usize nblocks)
{ {
const usize blocks_per_page = ARCH_PAGE_SIZE / m_block_size; const usize blocks_per_page = ARCH_PAGE_SIZE / m_block_size;
@ -785,16 +719,7 @@ namespace ATA
return atapi_read_pio(lba, out, nblocks * m_block_size); return atapi_read_pio(lba, out, nblocks * m_block_size);
} }
else else
{ todo();
while (nblocks > blocks_per_page)
{
TRY(ata_read_pio(lba, out, ARCH_PAGE_SIZE));
lba += blocks_per_page;
nblocks -= blocks_per_page;
out = offset_ptr(out, ARCH_PAGE_SIZE);
}
return ata_read_pio(lba, out, nblocks * m_block_size);
}
} }
void Drive::irq_handler() void Drive::irq_handler()

View File

@ -54,8 +54,6 @@ namespace ATA
enum CommandRegister : u8 enum CommandRegister : u8
{ {
CMD_ReadSectors = 0x20,
CMD_ReadSectorsExt = 0x24,
CMD_Identify = 0xec, CMD_Identify = 0xec,
CMD_Packet = 0xa0, CMD_Packet = 0xa0,
CMD_Identify_Packet = 0xa1 CMD_Identify_Packet = 0xa1
@ -182,11 +180,6 @@ namespace ATA
Result<void> atapi_read_pio(u64 lba, void* out, usize size); Result<void> atapi_read_pio(u64 lba, void* out, usize size);
Result<void> ata_read_pio(u64 lba, void* out, usize size);
void select_lba(u64 lba, usize count);
Result<void> read_pio_bytes(void* out, usize size);
Channel* m_channel; Channel* m_channel;
u8 m_drive_index; u8 m_drive_index;
@ -257,7 +250,6 @@ namespace ATA
} }
void select(u8 drive); void select(u8 drive);
void select(u8 base, u8 drive);
bool initialize(); bool initialize();
@ -278,7 +270,6 @@ namespace ATA
bool m_irq_called { false }; bool m_irq_called { false };
u8 m_current_drive = (u8)-1; u8 m_current_drive = (u8)-1;
u8 m_current_select_value = 0xff;
Option<Drive> m_drives[2]; Option<Drive> m_drives[2];
}; };

View File

@ -9,7 +9,6 @@
#pragma once #pragma once
#include <fcntl.h> #include <fcntl.h>
#include <luna/Attributes.h>
#include <luna/Buffer.h> #include <luna/Buffer.h>
#include <luna/Result.h> #include <luna/Result.h>
#include <luna/SharedPtr.h> #include <luna/SharedPtr.h>
@ -114,7 +113,7 @@ namespace os
/** /**
* @brief Write a string to this File. * @brief Write a string to this File.
* *
* @param str The string to write (doesn't have to be null-terminated). * @param str The string to write (can be not null-terminated).
* @return Result<void> Whether the operation succeeded. * @return Result<void> Whether the operation succeeded.
*/ */
Result<void> write(StringView str); Result<void> write(StringView str);
@ -127,24 +126,6 @@ namespace os
*/ */
Result<void> write(const Buffer& buf); Result<void> write(const Buffer& buf);
/**
* @brief Write a formatted string to this File.
*
* @param format The format string.
* @param ... The format arguments.
* @return Result<void> Whether the operation succeeded.
*/
Result<usize> write_formatted(const char* format, ...) _format(2, 3);
/**
* @brief Write a formatted string to this File.
*
* @param format The format string.
* @param args The format arguments.
* @return Result<void> Whether the operation succeeded.
*/
Result<usize> write_vformatted(const char* format, va_list args);
/** /**
* @brief Read a line from this File. * @brief Read a line from this File.
* *
@ -266,36 +247,36 @@ namespace os
/** /**
* @brief Print a formatted string to standard output. * @brief Print a formatted string to standard output.
* *
* @param format The format string (in the same format as printf(3)). * @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments. * @param ... The format arguments.
* @return Result<void> Whether the operation succeeded. * @return Result<void> Whether the operation succeeded.
*/ */
Result<void> print(const char* format, ...) _format(1, 2); Result<void> print(StringView fmt, ...);
/** /**
* @brief Print a newline-terminated formatted string to standard output. * @brief Print a newline-terminated formatted string to standard output.
* *
* @param format The format string (in the same format as printf(3)). * @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments. * @param ... The format arguments.
* @return Result<void> Whether the operation succeeded. * @return Result<void> Whether the operation succeeded.
*/ */
Result<void> println(const char* format, ...) _format(1, 2); Result<void> println(StringView fmt, ...);
/** /**
* @brief Print a formatted string to standard error. * @brief Print a formatted string to standard error.
* *
* @param format The format string (in the same format as printf(3)). * @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments. * @param ... The format arguments.
* @return Result<void> Whether the operation succeeded. * @return Result<void> Whether the operation succeeded.
*/ */
Result<void> eprint(const char* format, ...) _format(1, 2); Result<void> eprint(StringView fmt, ...);
/** /**
* @brief Print a newline-terminated formatted string to standard error. * @brief Print a newline-terminated formatted string to standard error.
* *
* @param format The format string (in the same format as printf(3)). * @param fmt The format string (in the same format as printf(3)).
* @param ... The format arguments. * @param ... The format arguments.
* @return Result<void> Whether the operation succeeded. * @return Result<void> Whether the operation succeeded.
*/ */
Result<void> eprintln(const char* format, ...) _format(1, 2); Result<void> eprintln(StringView fmt, ...);
} }

View File

@ -25,7 +25,6 @@ namespace os
static constexpr u8 ID = LAUNCH_DETACHED_ID; static constexpr u8 ID = LAUNCH_DETACHED_ID;
IPC_STRING(command); IPC_STRING(command);
bool search_in_path { false };
}; };
} }
} }

View File

@ -8,7 +8,6 @@
*/ */
#include <errno.h> #include <errno.h>
#include <luna/Format.h>
#include <luna/StringBuilder.h> #include <luna/StringBuilder.h>
#include <os/File.h> #include <os/File.h>
#include <unistd.h> #include <unistd.h>
@ -142,33 +141,6 @@ namespace os
return {}; return {};
} }
Result<usize> File::write_formatted(const char* format, ...)
{
va_list ap;
va_start(ap, format);
auto result = write_vformatted(format, ap);
va_end(ap);
return result;
}
Result<usize> File::write_vformatted(const char* format, va_list args)
{
auto rc = TRY(cstyle_format(
format,
[](char c, void* f) -> Result<void> {
TRY(((File*)f)->raw_write((const u8*)&c, 1));
return {};
},
this, args));
flush();
return rc;
}
Result<String> File::read_line() Result<String> File::read_line()
{ {
Vector<char> data; Vector<char> data;
@ -274,57 +246,64 @@ namespace os
setvbuf(m_file, NULL, mode, 0); setvbuf(m_file, NULL, mode, 0);
} }
Result<void> print(const char* format, ...) // FIXME: Do not allocate memory for printing.
Result<void> print_impl(SharedPtr<File> f, StringView fmt, va_list ap)
{
auto str = TRY(String::vformat(fmt, ap));
auto rc = f->write(str.view());
f->flush();
return rc;
}
Result<void> print(StringView fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, fmt);
TRY(File::standard_output()->write_vformatted(format, ap)); auto rc = print_impl(File::standard_output(), fmt, ap);
va_end(ap); va_end(ap);
return {}; return rc;
} }
Result<void> println(const char* format, ...) Result<void> println(StringView fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, fmt);
auto file = File::standard_output(); auto rc = print_impl(File::standard_output(), fmt, ap);
TRY(file->write_vformatted(format, ap));
TRY(file->write("\n"_sv));
va_end(ap); va_end(ap);
return {}; TRY(rc);
return File::standard_output()->write("\n"_sv);
} }
Result<void> eprint(const char* format, ...) Result<void> eprint(StringView fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, fmt);
TRY(File::standard_error()->write_vformatted(format, ap)); auto rc = print_impl(File::standard_error(), fmt, ap);
va_end(ap); va_end(ap);
return {}; return rc;
} }
Result<void> eprintln(const char* format, ...) Result<void> eprintln(StringView fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, fmt);
auto file = File::standard_error(); auto rc = print_impl(File::standard_error(), fmt, ap);
TRY(file->write_vformatted(format, ap));
TRY(file->write("\n"_sv));
va_end(ap); va_end(ap);
return {}; TRY(rc);
return File::standard_error()->write("\n"_sv);
} }
} }

View File

@ -23,7 +23,7 @@ namespace os::SharedMemory
if (fd < 0) if (fd < 0)
{ {
int olderr = errno; int olderr = errno;
os::eprintln("os: could not create shared memory region: shm_open failed (%s) - %s", path.chars(), os::eprintln("os: could not create shared memory region: shm_open failed (%s) - %s", path,
strerror(olderr)); strerror(olderr));
return err(olderr); return err(olderr);
} }

View File

@ -144,7 +144,7 @@ Result<int> luna_main(int argc, char** argv)
{ {
if (maybe_cmd.error() == EINTR) if (maybe_cmd.error() == EINTR)
{ {
os::print("\n"); os::println("");
continue; continue;
} }
return maybe_cmd.release_error(); return maybe_cmd.release_error();
@ -200,7 +200,7 @@ Result<int> luna_main(int argc, char** argv)
int sig = WTERMSIG(status); int sig = WTERMSIG(status);
if (sig != SIGINT && sig != SIGQUIT) os::println("[sh] Process %d exited: %s", child, strsignal(sig)); if (sig != SIGINT && sig != SIGQUIT) os::println("[sh] Process %d exited: %s", child, strsignal(sig));
else else
os::print("\n"); os::println("");
} }
} }

View File

@ -186,7 +186,7 @@ Result<int> luna_main(int argc, char** argv)
if (fds[i + 4].revents & POLLHUP) clients[i]->should_be_disconnected = true; if (fds[i + 4].revents & POLLHUP) clients[i]->should_be_disconnected = true;
if (clients[i]->should_be_disconnected) if (clients[i]->should_be_disconnected)
{ {
os::println("wind: Client %zu disconnected", i); os::println("wind: Client %d disconnected", i);
fds.remove_at(i + 4); fds.remove_at(i + 4);
auto client = clients.remove_at(i); auto client = clients.remove_at(i);
client->conn->disconnect(); client->conn->disconnect();