Skip to content

Commit

Permalink
userspace: port more programs/libraries, refine libreadline
Browse files Browse the repository at this point in the history
  • Loading branch information
moodyhunter committed Oct 31, 2023
1 parent 84e22d8 commit f6c40a5
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 89 deletions.
2 changes: 1 addition & 1 deletion arch/x86_64/x86_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ static void x86_com1_handler(u32 irq)
serial_device_read(&com1_console.device, &c, 1);
if (c == '\r')
c = '\n';
serial_console_write(&com1_console.con, &c, 1);
console_putc(&com1_console.con, c);
pr_cont("%c", c);
}
}

Expand Down
16 changes: 10 additions & 6 deletions cmake/add_mos_library.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ macro(add_mos_library_do_setup LIBNAME DEFINES PRIVATE_INCLUDE PUBLIC_INCLUDE)
endmacro()

macro(add_mos_library)
set(options USERSPACE_ONLY)
set(options USERSPACE_ONLY HOSTED_ONLY)
set(oneValueArgs NAME)
set(multiValueArgs SOURCES PUBLIC_INCLUDE_DIRECTORIES PRIVATE_INCLUDE_DIRECTORIES LINK_LIBRARIES)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
Expand Down Expand Up @@ -44,10 +44,12 @@ macro(add_mos_library)
endif()

# Create a userspace library
add_library(${ARG_NAME} STATIC ${ARG_SOURCES})
add_library(mos::${ARG_NAME} ALIAS ${ARG_NAME})

add_mos_library_do_setup(${ARG_NAME} "" "${ARG_PRIVATE_INCLUDE_DIRECTORIES}" "${ARG_PUBLIC_INCLUDE_DIRECTORIES}")
if (NOT ARG_HOSTED_ONLY)
add_library(${ARG_NAME} STATIC ${ARG_SOURCES})
add_library(mos::${ARG_NAME} ALIAS ${ARG_NAME})
add_mos_library_do_setup(${ARG_NAME} "" "${ARG_PRIVATE_INCLUDE_DIRECTORIES}" "${ARG_PUBLIC_INCLUDE_DIRECTORIES}")
endif()

if ("${ARG_NAME}" STREQUAL "stdlib")
# only need to add these to stdlib
Expand All @@ -61,8 +63,10 @@ macro(add_mos_library)
message(FATAL_ERROR "stdlib must not link to other libraries")
endif()
else()
target_link_libraries(${ARG_NAME} PUBLIC mos::stdlib)
target_link_libraries(${ARG_NAME} PUBLIC ${ARG_LINK_LIBRARIES})
if (NOT ARG_HOSTED_ONLY)
target_link_libraries(${ARG_NAME} PUBLIC mos::stdlib)
target_link_libraries(${ARG_NAME} PUBLIC ${ARG_LINK_LIBRARIES})
endif()

# Create a hosted userspace library
add_library(${ARG_NAME}_hosted SHARED ${ARG_SOURCES})
Expand Down
15 changes: 11 additions & 4 deletions userspace/libs/readline/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# SPDX-License-Identifier: GPL-3.0-or-later

add_library(readline libreadline.c)
target_include_directories(readline PUBLIC SYSTEM ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(readline PUBLIC mos::stdlib)
add_library(mos::readline ALIAS readline)
add_mos_library(
NAME libreadline
SOURCES
libreadline.c
PUBLIC_INCLUDE_DIRECTORIES
${CMAKE_CURRENT_LIST_DIR}/include
USERSPACE_ONLY
HOSTED_ONLY
)

add_to_initrd(TARGET libreadline_hosted /lib/)
5 changes: 3 additions & 2 deletions userspace/libs/readline/include/readline/libreadline.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#pragma once

#include <mos/mos_global.h>
#include <mos/types.h>

/**
Expand All @@ -10,12 +11,12 @@
* @param prompt Prompt to display
* @return char*
*/
char *readline(const char *prompt);
MOSAPI char *readline(const char *prompt);

/**
* @brief Read a line from a file descriptor
*
* @param fd File descriptor to read from
* @return char*
*/
char *get_line(fd_t fd);
MOSAPI char *get_line(fd_t fd);
102 changes: 58 additions & 44 deletions userspace/libs/readline/libreadline.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,49 @@

#include "readline/libreadline.h"

#include "mos/moslib_global.h"
#include "string.h"

#include <mos/syscall/usermode.h>
#include <mos_stdio.h>
#include <mos_stdlib.h>
#include <mos_string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define LINE_BUFFER_SIZE 1024

char *readline(const char *prompt)
{
const size_t prompt_length = strlen(prompt);
printf("%s", prompt);
fflush(stdout);

char *line_buffer = malloc(LINE_BUFFER_SIZE);
if (!line_buffer)
return NULL;

memzero(line_buffer, LINE_BUFFER_SIZE);
memset(line_buffer, 0, LINE_BUFFER_SIZE);

int insertion_point = 0; // index of the character that will be overwritten
int line_length = 0; // not including the null terminator

while (true)
{
fflush(stdout);
char c = getchar();

switch (c)
{
case 1:
insertion_point = 0;
const size_t pos = prompt_length + 1 + insertion_point;
printf("\033[%zuG", pos);
break;
case 5:
insertion_point = line_length;
const size_t pos2 = prompt_length + 1 + insertion_point;
printf("\033[%zuG", pos2);
break;
case '\r':
case '\n':
line_buffer[line_length] = '\0';
printf("\n");
fflush(stdout);
return line_buffer;
case '\f':
printf("\033[2J\033[H"); // clear screen
Expand Down Expand Up @@ -80,27 +90,27 @@ char *readline(const char *prompt)
{
insertion_point--;
line_length--;
printf("\b \b");
printf("\b \b"); // move cursor back, clear last character, move cursor back again
}
else
{
// move the rest of the line to the right
for (int i = line_length; i > insertion_point; i--)
// move the rest of the line to the left
insertion_point--;
line_length--;
printf("\b"); // move cursor back

for (int i = insertion_point; i < line_length; i++)
{
line_buffer[i] = line_buffer[i - 1];
line_buffer[i] = line_buffer[i + 1];
printf("%c", line_buffer[i]);
}

// move the cursor forward
for (int i = insertion_point; i < line_length; i++)
printf("\033[C");

// clear the last character
printf(" \b");

// move the insertion point back
insertion_point--;
line_length--;
// move the cursor back to the insertion point
for (int i = insertion_point; i < line_length; i++)
printf("\b");
}
}
break;
Expand All @@ -113,18 +123,24 @@ char *readline(const char *prompt)
if (c == 'D')
{
if (insertion_point > 0)
{
insertion_point--;
printf("\b"); // move cursor left
}
else
printf("\033[C"); // move the cursor back to the insertion point
}
else if (c == 'C')
{
if (insertion_point < line_length)
{
insertion_point++;
printf("\033[C"); // move cursor right
}
else
printf("\033[D"); // move the cursor back to the insertion point
}
else if (c == 'A')
{
printf("\033[B"); // move the cursor back to the insertion point
}
else if (c == 'B')
{
printf("\033[A"); // move the cursor back to the insertion point
}
else if (c == '3')
{
Expand All @@ -143,12 +159,11 @@ char *readline(const char *prompt)
// clear the last character
printf(" \b");

line_length--;

// move the cursor back
for (int i = insertion_point; i < line_length; i++)
printf("\b");

// move the insertion point back
line_length--;
}
}
}
Expand All @@ -159,20 +174,16 @@ char *readline(const char *prompt)
}
break;
default:
if (line_length < LINE_BUFFER_SIZE - 1)
{
line_buffer[insertion_point] = c;
insertion_point++;
line_length++;
printf("%c", c);
}
else
if (line_length + 1 >= LINE_BUFFER_SIZE)
{
// buffer is full
fatal_abort("readline: line too long");
puts("readline: line too long");
abort();
break;
}

line_length++;

// if we're not at the end of the line, we need to move the rest of the line
if (insertion_point < line_length)
{
Expand All @@ -183,22 +194,25 @@ char *readline(const char *prompt)
}

// print the rest of the line
for (int i = insertion_point; i < line_length; i++)
for (int i = insertion_point + 1; i < line_length; i++)
{
printf("%c", line_buffer[i]);
}

// move the cursor back to the insertion point
for (int i = insertion_point; i < line_length; i++)
for (int i = insertion_point + 1; i < line_length; i++)
{
printf("\b");
}
}

line_buffer[insertion_point] = c;
insertion_point++;
break;
}
}

fflush(stdout);
return "";
}

Expand All @@ -208,21 +222,21 @@ char *get_line(fd_t fd)
if (!line_buffer)
return NULL;

memzero(line_buffer, LINE_BUFFER_SIZE);
memset(line_buffer, 0, LINE_BUFFER_SIZE);

char c;
int i = 0;
while (i < LINE_BUFFER_SIZE - 1)
{
size_t read = syscall_io_read(fd, &c, 1);
size_t readsz = read(fd, &c, 1);

if (read == 0 && i == 0)
if (readsz == 0 && i == 0)
{
free(line_buffer);
return NULL; // EOF
}

if (read != 1)
if (readsz != 1)
break;

if (c == '\n')
Expand Down
1 change: 0 additions & 1 deletion userspace/programs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ add_subdirectory(init)
add_subdirectory(kdebug)
add_subdirectory(lazybox)
add_subdirectory(mossh)
add_subdirectory(signal)

add_subdirectory(2048)
5 changes: 2 additions & 3 deletions userspace/programs/kdebug/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-3.0-or-later

add_executable(kdebug main.c)
target_link_libraries(kdebug PRIVATE mos::readline)

setup_userspace_program(kdebug /programs "Debug kernel parameters")
target_link_libraries(kdebug PRIVATE mos::include mos::libreadline_hosted)
add_to_initrd(TARGET kdebug /programs)
9 changes: 5 additions & 4 deletions userspace/programs/kdebug/main.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#include <fcntl.h>
#include <mos_stdio.h>
#include <mos_stdlib.h>
#include <mos_string.h>
#include <mos/mos_global.h>
#include <readline/libreadline.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 4096

Expand Down Expand Up @@ -92,7 +93,7 @@ static void do_memstat(void)

static void do_leave(void)
{
syscall_exit(0);
exit(0);
}

const struct
Expand Down
2 changes: 1 addition & 1 deletion userspace/programs/mossh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ add_executable(mossh
cmdline.c
)

target_link_libraries(mossh PRIVATE mos::argparse_hosted)
target_link_libraries(mossh PRIVATE mos::argparse_hosted mos::libreadline_hosted)
add_to_initrd(TARGET mossh /programs)
17 changes: 1 addition & 16 deletions userspace/programs/mossh/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "mossh.h"

#include <fcntl.h>
#include <readline/libreadline.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -55,22 +56,6 @@ static char *string_trim(char *in)
return in;
}

char *readline(const char *prompt)
{
char *line = NULL;
size_t linecap = 0;
printf("%s", prompt);
fflush(stdout);
ssize_t linelen = getline(&line, &linecap, stdin);
if (linelen <= 0)
{
free(line);
return NULL;
}
line[linelen - 1] = '\0'; // remove newline
return line;
}

static pid_t spawn(const char *path, const char *const argv[])
{
pid_t pid = fork();
Expand Down
1 change: 1 addition & 0 deletions userspace/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_subdirectory(libstdcxx)

add_subdirectory(libc-test)
add_simple_rust_project("${CMAKE_CURRENT_LIST_DIR}/rust-test" rust-test "/tests/")
add_subdirectory(signal)

add_executable(test-launcher test-main.c)
setup_userspace_program(test-launcher /tests "Userspace test launcher")
Loading

0 comments on commit f6c40a5

Please sign in to comment.