mirror of
https://github.com/RGBCube/serenity
synced 2025-05-19 20:35:06 +00:00
Add some simple write buffering to LibC's stdio.
Plumb it all the way to the VirtualConsole. Also fix /bin/cat to write() the whole chunks we get from read() directly to stdout.
This commit is contained in:
parent
e287f8ef3a
commit
da3857b0c2
10 changed files with 42 additions and 22 deletions
|
@ -29,15 +29,19 @@
|
||||||
#define VALIDATE_USER_READ(b, s) \
|
#define VALIDATE_USER_READ(b, s) \
|
||||||
do { \
|
do { \
|
||||||
LinearAddress laddr((dword)(b)); \
|
LinearAddress laddr((dword)(b)); \
|
||||||
if (!validate_user_read(laddr) || !validate_user_read(laddr.offset((s) - 1))) \
|
if (!validate_user_read(laddr) || !validate_user_read(laddr.offset((s) - 1))) { \
|
||||||
|
dbgprintf("Bad read address passed to syscall: %p +%u\n", laddr.get(), (s)); \
|
||||||
return -EFAULT; \
|
return -EFAULT; \
|
||||||
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define VALIDATE_USER_WRITE(b, s) \
|
#define VALIDATE_USER_WRITE(b, s) \
|
||||||
do { \
|
do { \
|
||||||
LinearAddress laddr((dword)(b)); \
|
LinearAddress laddr((dword)(b)); \
|
||||||
if (!validate_user_write(laddr) || !validate_user_write(laddr.offset((s) - 1))) \
|
if (!validate_user_write(laddr) || !validate_user_write(laddr.offset((s) - 1))) { \
|
||||||
|
dbgprintf("Bad write address passed to syscall: %p +%u\n", laddr.get(), (s)); \
|
||||||
return -EFAULT; \
|
return -EFAULT; \
|
||||||
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static const DWORD defaultStackSize = 16384;
|
static const DWORD defaultStackSize = 16384;
|
||||||
|
|
|
@ -26,8 +26,7 @@ ssize_t TTY::read(byte* buffer, size_t size)
|
||||||
|
|
||||||
ssize_t TTY::write(const byte* buffer, size_t size)
|
ssize_t TTY::write(const byte* buffer, size_t size)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < size; ++i)
|
onTTYWrite(buffer, size);
|
||||||
onTTYWrite(buffer[i]);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ protected:
|
||||||
TTY(unsigned major, unsigned minor);
|
TTY(unsigned major, unsigned minor);
|
||||||
void emit(byte);
|
void emit(byte);
|
||||||
|
|
||||||
virtual void onTTYWrite(byte) = 0;
|
virtual void onTTYWrite(const byte*, size_t) = 0;
|
||||||
|
|
||||||
void interrupt();
|
void interrupt();
|
||||||
|
|
||||||
|
|
|
@ -320,7 +320,6 @@ void VirtualConsole::put_character_at(unsigned row, unsigned column, byte ch)
|
||||||
|
|
||||||
void VirtualConsole::on_char(byte ch, bool shouldEmit)
|
void VirtualConsole::on_char(byte ch, bool shouldEmit)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
|
||||||
if (shouldEmit)
|
if (shouldEmit)
|
||||||
emit(ch);
|
emit(ch);
|
||||||
|
|
||||||
|
@ -397,15 +396,18 @@ void VirtualConsole::onKeyPress(Keyboard::Key key)
|
||||||
|
|
||||||
void VirtualConsole::onConsoleReceive(byte ch)
|
void VirtualConsole::onConsoleReceive(byte ch)
|
||||||
{
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
auto old_attribute = m_current_attribute;
|
auto old_attribute = m_current_attribute;
|
||||||
m_current_attribute = 0x03;
|
m_current_attribute = 0x03;
|
||||||
on_char(ch, false);
|
on_char(ch, false);
|
||||||
m_current_attribute = old_attribute;
|
m_current_attribute = old_attribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualConsole::onTTYWrite(byte ch)
|
void VirtualConsole::onTTYWrite(const byte* data, size_t size)
|
||||||
{
|
{
|
||||||
on_char(ch, false);
|
InterruptDisabler disabler;
|
||||||
|
for (size_t i = 0; i < size; ++i)
|
||||||
|
on_char(data[i], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
String VirtualConsole::ttyName() const
|
String VirtualConsole::ttyName() const
|
||||||
|
|
|
@ -23,7 +23,7 @@ private:
|
||||||
virtual void onConsoleReceive(byte) override;
|
virtual void onConsoleReceive(byte) override;
|
||||||
|
|
||||||
// ^TTY
|
// ^TTY
|
||||||
virtual void onTTYWrite(byte) override;
|
virtual void onTTYWrite(const byte*, size_t) override;
|
||||||
virtual String ttyName() const override;
|
virtual String ttyName() const override;
|
||||||
|
|
||||||
void set_active(bool);
|
void set_active(bool);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <Kernel/Syscall.h>
|
#include <Kernel/Syscall.h>
|
||||||
#include <AK/StringImpl.h>
|
#include <AK/StringImpl.h>
|
||||||
|
|
||||||
|
@ -20,6 +21,8 @@ extern "C" int _start()
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
|
memset(__default_streams, 0, sizeof(__default_streams));
|
||||||
|
|
||||||
__default_streams[0].fd = 0;
|
__default_streams[0].fd = 0;
|
||||||
stdin = &__default_streams[0];
|
stdin = &__default_streams[0];
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,11 @@ int fflush(FILE* stream)
|
||||||
// FIXME: Implement buffered streams, duh.
|
// FIXME: Implement buffered streams, duh.
|
||||||
if (!stream)
|
if (!stream)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
return 0;
|
if (!stream->write_buffer_index)
|
||||||
|
return 0;
|
||||||
|
int rc = write(stream->fd, stream->write_buffer, stream->write_buffer_index);
|
||||||
|
stream->write_buffer_index = 0;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* fgets(char* buffer, int size, FILE* stream)
|
char* fgets(char* buffer, int size, FILE* stream)
|
||||||
|
@ -71,7 +75,10 @@ int getchar()
|
||||||
int fputc(int ch, FILE* stream)
|
int fputc(int ch, FILE* stream)
|
||||||
{
|
{
|
||||||
assert(stream);
|
assert(stream);
|
||||||
write(stream->fd, &ch, 1);
|
assert(stream->write_buffer_index < __STDIO_FILE_BUFFER_SIZE);
|
||||||
|
stream->write_buffer[stream->write_buffer_index++] = ch;
|
||||||
|
if (ch == '\n' || stream->write_buffer_index >= __STDIO_FILE_BUFFER_SIZE)
|
||||||
|
fflush(stream);
|
||||||
if (stream->eof)
|
if (stream->eof)
|
||||||
return EOF;
|
return EOF;
|
||||||
return (byte)ch;
|
return (byte)ch;
|
||||||
|
@ -99,7 +106,7 @@ int fputs(const char* s, FILE* stream)
|
||||||
|
|
||||||
int puts(const char* s)
|
int puts(const char* s)
|
||||||
{
|
{
|
||||||
fputs(s, stdout);
|
return fputs(s, stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearerr(FILE* stream)
|
void clearerr(FILE* stream)
|
||||||
|
@ -128,6 +135,7 @@ size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
|
||||||
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream)
|
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream)
|
||||||
{
|
{
|
||||||
assert(stream);
|
assert(stream);
|
||||||
|
fflush(stream);
|
||||||
ssize_t nwritten = write(stream->fd, ptr, nmemb * size);
|
ssize_t nwritten = write(stream->fd, ptr, nmemb * size);
|
||||||
if (nwritten < 0)
|
if (nwritten < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -162,7 +170,7 @@ static void sys_putch(char*&, char ch)
|
||||||
static FILE* __current_stream = nullptr;
|
static FILE* __current_stream = nullptr;
|
||||||
static void stream_putch(char*&, char ch)
|
static void stream_putch(char*&, char ch)
|
||||||
{
|
{
|
||||||
write(__current_stream->fd, &ch, 1);
|
fputc(ch, __current_stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fprintf(FILE* fp, const char* fmt, ...)
|
int fprintf(FILE* fp, const char* fmt, ...)
|
||||||
|
@ -211,9 +219,8 @@ FILE* fopen(const char* pathname, const char* mode)
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto* fp = (FILE*)malloc(sizeof(FILE));
|
auto* fp = (FILE*)malloc(sizeof(FILE));
|
||||||
|
memset(fp, 0, sizeof(FILE));
|
||||||
fp->fd = fd;
|
fp->fd = fd;
|
||||||
fp->eof = false;
|
|
||||||
fp->error = 0;
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,9 +230,8 @@ FILE* fdopen(int fd, const char* mode)
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto* fp = (FILE*)malloc(sizeof(FILE));
|
auto* fp = (FILE*)malloc(sizeof(FILE));
|
||||||
|
memset(fp, 0, sizeof(FILE));
|
||||||
fp->fd = fd;
|
fp->fd = fd;
|
||||||
fp->eof = false;
|
|
||||||
fp->error = 0;
|
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
#ifndef EOF
|
||||||
#ifndef EOF
|
|
||||||
#define EOF (-1)
|
#define EOF (-1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -13,10 +12,16 @@ __BEGIN_DECLS
|
||||||
#define SEEK_CUR 1
|
#define SEEK_CUR 1
|
||||||
#define SEEK_END 2
|
#define SEEK_END 2
|
||||||
|
|
||||||
|
#define __STDIO_FILE_BUFFER_SIZE 128
|
||||||
|
|
||||||
struct __STDIO_FILE {
|
struct __STDIO_FILE {
|
||||||
int fd;
|
int fd;
|
||||||
int eof;
|
int eof;
|
||||||
int error;
|
int error;
|
||||||
|
char read_buffer[__STDIO_FILE_BUFFER_SIZE];
|
||||||
|
size_t read_buffer_index;
|
||||||
|
char write_buffer[__STDIO_FILE_BUFFER_SIZE];
|
||||||
|
size_t write_buffer_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct __STDIO_FILE FILE;
|
typedef struct __STDIO_FILE FILE;
|
||||||
|
|
|
@ -17,7 +17,7 @@ int main(int argc, char** argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char buf[1024];
|
char buf[4096];
|
||||||
ssize_t nread = read(fd, buf, sizeof(buf));
|
ssize_t nread = read(fd, buf, sizeof(buf));
|
||||||
if (nread == 0)
|
if (nread == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -25,8 +25,7 @@ int main(int argc, char** argv)
|
||||||
printf("read() error: %s\n", strerror(errno));
|
printf("read() error: %s\n", strerror(errno));
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
for (ssize_t i = 0; i < nread; ++i)
|
write(1, buf, nread);
|
||||||
putchar(buf[i]);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ static void prompt()
|
||||||
printf("# ");
|
printf("# ");
|
||||||
else
|
else
|
||||||
printf("\033[31;1m%s\033[0m@\033[37;1m%s\033[0m:\033[32;1m%s\033[0m$> ", g->username.characters(), g->hostname, g->cwd.characters());
|
printf("\033[31;1m%s\033[0m@\033[37;1m%s\033[0m:\033[32;1m%s\033[0m$> ", g->username.characters(), g->hostname, g->cwd.characters());
|
||||||
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sh_pwd(int, const char**)
|
static int sh_pwd(int, const char**)
|
||||||
|
@ -347,6 +348,7 @@ int main(int, char**)
|
||||||
}
|
}
|
||||||
for (ssize_t i = 0; i < nread; ++i) {
|
for (ssize_t i = 0; i < nread; ++i) {
|
||||||
putchar(keybuf[i]);
|
putchar(keybuf[i]);
|
||||||
|
fflush(stdout);
|
||||||
if (keybuf[i] != '\n') {
|
if (keybuf[i] != '\n') {
|
||||||
linebuf[linedx++] = keybuf[i];
|
linebuf[linedx++] = keybuf[i];
|
||||||
linebuf[linedx] = '\0';
|
linebuf[linedx] = '\0';
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue