libc: Start switching to /dev/console for console IO and add a proper init
This commit is contained in:
parent
8c831a6906
commit
629ed9e43b
@ -6,5 +6,5 @@ function(luna_app SOURCE_FILE APP_NAME)
|
||||
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
|
||||
endfunction()
|
||||
|
||||
luna_app(app.c app)
|
||||
luna_app(init.c init)
|
||||
luna_app(hello.c hello)
|
||||
|
39
apps/app.c
39
apps/app.c
@ -1,39 +0,0 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void bye()
|
||||
{
|
||||
printf("byeee!\n");
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
atexit(bye);
|
||||
printf("Welcome to %s from userspace (pid %d)!\n", "Luna", getpid());
|
||||
|
||||
FILE* f = fopen("/etc/motd", "r");
|
||||
if (!f)
|
||||
{
|
||||
perror("fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
char buffer[512];
|
||||
size_t nread = fread(buffer, 1, sizeof(buffer), f);
|
||||
buffer[nread] = 0;
|
||||
|
||||
printf("/etc/motd says: %s", buffer);
|
||||
|
||||
fclose(f);
|
||||
|
||||
time_t now = time(NULL);
|
||||
printf("date: %s", ctime(&now));
|
||||
|
||||
// FIXME: Add libc wrapper.
|
||||
syscall(SYS_exec, "/bin/hello");
|
||||
}
|
38
apps/init.c
Normal file
38
apps/init.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define xmknod(path, mode, maj, min) \
|
||||
if (mknod(path, mode, makedev(maj, min)) < 0) exit(255);
|
||||
|
||||
// Too early for console logs (/dev/console is created here!), so we have to resort to exiting with a weird exit code in
|
||||
// case of failure.
|
||||
static void populate_devfs()
|
||||
{
|
||||
if (mkdir("/dev", 0755) < 0 && errno != EEXIST) exit(255);
|
||||
|
||||
xmknod("/dev/console", 0666, 1, 0);
|
||||
xmknod("/dev/null", 0666, 2, 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
if (getpid() != 1)
|
||||
{
|
||||
printf("error: init not running as PID 1.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
populate_devfs();
|
||||
|
||||
// Before this point, we don't even have an stdout and stderr. Set it up now so that child processes (and us) can
|
||||
// print stuff.
|
||||
stdout = fopen("/dev/console", "w");
|
||||
stderr = fopen("/dev/console", "w");
|
||||
|
||||
fputs("Hello, world!", stderr);
|
||||
}
|
@ -66,9 +66,9 @@ static void init_vfs()
|
||||
|
||||
static Result<void> try_init_userspace()
|
||||
{
|
||||
auto app = TRY(VFS::resolve_path("/bin/app"));
|
||||
auto init = TRY(VFS::resolve_path("/bin/init"));
|
||||
|
||||
TRY(Scheduler::new_userspace_thread(app));
|
||||
TRY(Scheduler::new_userspace_thread(init));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ set(SOURCES
|
||||
src/atexit.cpp
|
||||
src/ctype.cpp
|
||||
src/time.cpp
|
||||
src/init.cpp
|
||||
src/sys/stat.cpp
|
||||
src/sys/mman.cpp
|
||||
)
|
||||
|
@ -16,7 +16,9 @@ typedef struct
|
||||
|
||||
#define EOF -1
|
||||
|
||||
extern FILE* stdout;
|
||||
extern FILE* stderr;
|
||||
#define stdout stdout
|
||||
#define stderr stderr
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -29,6 +31,9 @@ extern "C"
|
||||
/* Open a file and binds a stream to it. */
|
||||
FILE* fopen(const char* path, const char* mode);
|
||||
|
||||
/* Bind a stream to a file descriptor. */
|
||||
FILE* fdopen(int fd, const char* mode);
|
||||
|
||||
/* Close a file and frees up its stream. */
|
||||
int fclose(FILE* stream);
|
||||
|
||||
@ -62,6 +67,18 @@ extern "C"
|
||||
/* Return whether the end-of-file indicator was set in stream. */
|
||||
int feof(FILE* stream);
|
||||
|
||||
/* Write a character to stream. */
|
||||
int fputc(int c, FILE* stream);
|
||||
|
||||
/* Write a character to stream. */
|
||||
int putc(int c, FILE* stream);
|
||||
|
||||
/* Write a character to standard output. */
|
||||
int putchar(int c);
|
||||
|
||||
/* Write a string to stream. */
|
||||
int fputs(const char* str, FILE* stream);
|
||||
|
||||
/* Clear the error and end-of-file indicators in stream. */
|
||||
void clearerr(FILE* stream);
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define STDOUT_FILENO 0
|
||||
#define STDERR_FILENO 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
.global _start
|
||||
.extern exit
|
||||
.extern libc_init
|
||||
_start:
|
||||
# Set up end of the stack frame linked list.
|
||||
movq $0, %rbp
|
||||
@ -9,6 +10,8 @@ _start:
|
||||
pushq %rbp # rbp=0
|
||||
movq %rsp, %rbp
|
||||
|
||||
call libc_init
|
||||
|
||||
# Run the global constructors.
|
||||
call _init
|
||||
|
||||
|
11
libc/src/init.cpp
Normal file
11
libc/src/init.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void libc_init()
|
||||
{
|
||||
stdout = fdopen(STDOUT_FILENO, "w");
|
||||
stderr = fdopen(STDERR_FILENO, "w");
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
FILE* stderr = nullptr;
|
||||
FILE* stdout = nullptr;
|
||||
|
||||
static int fopen_parse_mode(const char* mode)
|
||||
{
|
||||
@ -41,13 +42,13 @@ extern "C"
|
||||
|
||||
if ((flags = fopen_parse_mode(mode)) < 0) return nullptr;
|
||||
|
||||
int fd = open(path, flags, 0666);
|
||||
if (fd < 0) return nullptr;
|
||||
|
||||
FILE* f = (FILE*)malloc(sizeof(FILE));
|
||||
if (!f)
|
||||
if (!f) { return nullptr; }
|
||||
|
||||
int fd = open(path, flags, 0666);
|
||||
if (fd < 0)
|
||||
{
|
||||
close(fd);
|
||||
free(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -57,6 +58,25 @@ extern "C"
|
||||
return f;
|
||||
}
|
||||
|
||||
FILE* fdopen(int fd, const char* mode)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if ((flags = fopen_parse_mode(mode)) < 0) return nullptr;
|
||||
|
||||
// FIXME: We do verify that fd is valid, but not that the mode is compatible.
|
||||
long rc = lseek(fd, 0, SEEK_CUR);
|
||||
if (rc < 0) return nullptr;
|
||||
|
||||
FILE* f = (FILE*)malloc(sizeof(FILE));
|
||||
if (!f) { return nullptr; }
|
||||
|
||||
f->_fd = fd;
|
||||
clearerr(f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
int fclose(FILE* stream)
|
||||
{
|
||||
if (close(stream->_fd) < 0) return EOF;
|
||||
@ -148,6 +168,30 @@ extern "C"
|
||||
return stream->_eof;
|
||||
}
|
||||
|
||||
int fputc(int c, FILE* stream)
|
||||
{
|
||||
u8 value = (u8)c;
|
||||
ssize_t rc = write(stream->_fd, &value, 1);
|
||||
if (rc <= 0) return EOF;
|
||||
return c;
|
||||
}
|
||||
|
||||
int putc(int c, FILE* stream)
|
||||
{
|
||||
return fputc(c, stream);
|
||||
}
|
||||
|
||||
int putchar(int c)
|
||||
{
|
||||
return fputc(c, stdout);
|
||||
}
|
||||
|
||||
int fputs(const char* str, FILE* stream)
|
||||
{
|
||||
ssize_t rc = write(stream->_fd, str, strlen(str));
|
||||
return (rc < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
void clearerr(FILE* stream)
|
||||
{
|
||||
stream->_eof = stream->_err = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user