Compare commits
No commits in common. "cb1ef3e404259dbda2ad1bbca522e0c30c721d96" and "8c831a69068a4b0b4c31cf2716d446a91b473509" have entirely different histories.
cb1ef3e404
...
8c831a6906
@ -6,5 +6,5 @@ function(luna_app SOURCE_FILE APP_NAME)
|
||||
install(TARGETS ${APP_NAME} DESTINATION ${LUNA_ROOT}/initrd/bin)
|
||||
endfunction()
|
||||
|
||||
luna_app(init.c init)
|
||||
luna_app(app.c app)
|
||||
luna_app(hello.c hello)
|
||||
|
39
apps/app.c
Normal file
39
apps/app.c
Normal file
@ -0,0 +1,39 @@
|
||||
#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
38
apps/init.c
@ -1,38 +0,0 @@
|
||||
#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");
|
||||
|
||||
fprintf(stderr, "init is running as PID %d\n", getpid());
|
||||
}
|
@ -14,6 +14,6 @@ Result<usize> ConsoleDevice::read(u8*, usize, usize) const
|
||||
|
||||
Result<usize> ConsoleDevice::write(const u8* buf, usize, usize length)
|
||||
{
|
||||
TextConsole::write((const char*)buf, length);
|
||||
TextConsole::print((const char*)buf);
|
||||
return length;
|
||||
}
|
||||
|
@ -66,9 +66,9 @@ static void init_vfs()
|
||||
|
||||
static Result<void> try_init_userspace()
|
||||
{
|
||||
auto init = TRY(VFS::resolve_path("/bin/init"));
|
||||
auto app = TRY(VFS::resolve_path("/bin/app"));
|
||||
|
||||
TRY(Scheduler::new_userspace_thread(init));
|
||||
TRY(Scheduler::new_userspace_thread(app));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -172,12 +172,6 @@ namespace TextConsole
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void> write(const char* str, usize len)
|
||||
{
|
||||
while (len--) TRY(putchar(*str++));
|
||||
return {};
|
||||
}
|
||||
|
||||
void wprint(const wchar_t* str)
|
||||
{
|
||||
while (*str) putwchar(*str++);
|
||||
|
@ -14,7 +14,6 @@ namespace TextConsole
|
||||
u32 background();
|
||||
void move_to(u32 x, u32 y);
|
||||
Result<void> print(const char* str);
|
||||
Result<void> write(const char* str, usize len);
|
||||
void wprint(const wchar_t* str);
|
||||
Result<void> println(const char* str);
|
||||
void wprintln(const wchar_t* str);
|
||||
|
@ -12,7 +12,6 @@ set(SOURCES
|
||||
src/atexit.cpp
|
||||
src/ctype.cpp
|
||||
src/time.cpp
|
||||
src/init.cpp
|
||||
src/sys/stat.cpp
|
||||
src/sys/mman.cpp
|
||||
)
|
||||
|
@ -16,9 +16,7 @@ typedef struct
|
||||
|
||||
#define EOF -1
|
||||
|
||||
extern FILE* stdout;
|
||||
extern FILE* stderr;
|
||||
#define stdout stdout
|
||||
#define stderr stderr
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -31,9 +29,6 @@ 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);
|
||||
|
||||
@ -67,28 +62,13 @@ 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);
|
||||
|
||||
void setbuf(FILE*, char*);
|
||||
|
||||
/* Write formatted output to a file. */
|
||||
int fprintf(FILE* stream, const char* format, ...);
|
||||
|
||||
/* Write formatted output to a file. */
|
||||
int vfprintf(FILE* stream, const char* format, va_list ap);
|
||||
int fprintf(FILE*, const char*, ...);
|
||||
int vfprintf(FILE*, const char*, va_list);
|
||||
|
||||
/* Write formatted output into a buffer. */
|
||||
int sprintf(char* buf, const char* format, ...);
|
||||
@ -102,15 +82,15 @@ extern "C"
|
||||
/* Write up to max bytes of formatted output into a buffer. */
|
||||
int vsnprintf(char*, size_t, const char*, va_list);
|
||||
|
||||
/* Write formatted output to standard output. */
|
||||
int vprintf(const char*, va_list ap);
|
||||
|
||||
/* Write formatted output to standard output. */
|
||||
int printf(const char*, ...);
|
||||
|
||||
/* Write a string followed by a newline to standard output. */
|
||||
int puts(const char* s);
|
||||
|
||||
/* Output a message to the console. */
|
||||
int console_write(const char* msg, size_t size);
|
||||
|
||||
/* Write an error message to standard error. */
|
||||
void perror(const char* s);
|
||||
|
||||
|
@ -10,9 +10,6 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define STDOUT_FILENO 0
|
||||
#define STDERR_FILENO 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
.global _start
|
||||
.extern exit
|
||||
.extern libc_init
|
||||
_start:
|
||||
# Set up end of the stack frame linked list.
|
||||
movq $0, %rbp
|
||||
@ -10,8 +9,6 @@ _start:
|
||||
pushq %rbp # rbp=0
|
||||
movq %rsp, %rbp
|
||||
|
||||
call libc_init
|
||||
|
||||
# Run the global constructors.
|
||||
call _init
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void libc_init()
|
||||
{
|
||||
stdout = fdopen(STDOUT_FILENO, "w");
|
||||
stderr = fdopen(STDERR_FILENO, "w");
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
FILE* stderr = nullptr;
|
||||
FILE* stdout = nullptr;
|
||||
|
||||
static int fopen_parse_mode(const char* mode)
|
||||
{
|
||||
@ -30,19 +29,25 @@ static int fopen_parse_mode(const char* mode)
|
||||
|
||||
extern "C"
|
||||
{
|
||||
int console_write(const char* str, size_t size)
|
||||
{
|
||||
long rc = syscall(SYS_console_write, str, size);
|
||||
__errno_return(rc, int);
|
||||
}
|
||||
|
||||
FILE* fopen(const char* path, const char* mode)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if ((flags = fopen_parse_mode(mode)) < 0) return nullptr;
|
||||
|
||||
FILE* f = (FILE*)malloc(sizeof(FILE));
|
||||
if (!f) { return nullptr; }
|
||||
|
||||
int fd = open(path, flags, 0666);
|
||||
if (fd < 0)
|
||||
if (fd < 0) return nullptr;
|
||||
|
||||
FILE* f = (FILE*)malloc(sizeof(FILE));
|
||||
if (!f)
|
||||
{
|
||||
free(f);
|
||||
close(fd);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -52,25 +57,6 @@ 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;
|
||||
@ -162,30 +148,6 @@ 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;
|
||||
@ -225,46 +187,19 @@ extern "C"
|
||||
return rc;
|
||||
}
|
||||
|
||||
int vfprintf(FILE* stream, const char* format, va_list ap)
|
||||
{
|
||||
usize rc = cstyle_format(
|
||||
format,
|
||||
[](char c, void* f) -> Result<void> {
|
||||
int rc = fputc(c, (FILE*)f);
|
||||
if (rc == EOF) return err(errno);
|
||||
return {};
|
||||
},
|
||||
stream, ap)
|
||||
.value_or(-1);
|
||||
|
||||
if (rc == (usize)-1) return -1;
|
||||
|
||||
return (int)rc;
|
||||
}
|
||||
|
||||
int fprintf(FILE* stream, const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
int rc = vfprintf(stream, format, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int vprintf(const char* format, va_list ap)
|
||||
{
|
||||
return vfprintf(stdout, format, ap);
|
||||
}
|
||||
|
||||
int printf(const char* format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
int rc = vfprintf(stdout, format, ap);
|
||||
int rc = (int)cstyle_format(
|
||||
format,
|
||||
[](char c, void*) -> Result<void> {
|
||||
console_write(&c, 1);
|
||||
return {};
|
||||
},
|
||||
nullptr, ap)
|
||||
.value();
|
||||
|
||||
va_end(ap);
|
||||
|
||||
@ -273,22 +208,30 @@ extern "C"
|
||||
|
||||
int puts(const char* s)
|
||||
{
|
||||
if (fputs(s, stdout) < 0) return -1;
|
||||
if (putchar('\n') == EOF) return -1;
|
||||
if (console_write(s, strlen(s)) < 0) return -1;
|
||||
if (console_write("\n", 1) < 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void perror(const char* s)
|
||||
{
|
||||
// FIXME: Output to stderr when available.
|
||||
int err = errno;
|
||||
if (s && *s) fprintf(stderr, "%s: ", s);
|
||||
fprintf(stderr, "%s\n", strerror(err));
|
||||
if (s && *s) printf("%s: ", s);
|
||||
printf("%s\n", strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
void debug_log_impl(const char* format, va_list ap)
|
||||
{
|
||||
vfprintf(stderr, format, ap);
|
||||
fputc('\n', stderr);
|
||||
cstyle_format(
|
||||
format,
|
||||
[](char c, void*) -> Result<void> {
|
||||
console_write(&c, 1);
|
||||
return {};
|
||||
},
|
||||
nullptr, ap)
|
||||
.value();
|
||||
console_write("\n", 1);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user