mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add ONLCR and OCRNL.
This is a compatible ABI change.
This commit is contained in:
parent
9603be8e65
commit
d720f16537
8 changed files with 148 additions and 17 deletions
2
Makefile
2
Makefile
|
@ -157,7 +157,7 @@ sysroot-system: sysroot-fsh sysroot-base-headers
|
|||
echo 'ID=sortix' && \
|
||||
echo 'VERSION_ID="$(VERSION)"' && \
|
||||
echo 'PRETTY_NAME="Sortix $(VERSION)"' && \
|
||||
echo 'SORTIX_ABI=0.0' && \
|
||||
echo 'SORTIX_ABI=0.1' && \
|
||||
true) > "$(SYSROOT)/etc/sortix-release"
|
||||
echo /etc/sortix-release >> "$(SYSROOT)/tix/manifest/system"
|
||||
ln -sf sortix-release "$(SYSROOT)/etc/os-release"
|
||||
|
|
|
@ -45,6 +45,7 @@ extern size_t fallback_framebuffer_height;
|
|||
|
||||
extern TextBufferHandle* device_textbufhandle;
|
||||
extern size_t (*device_callback)(void*, const char*, size_t);
|
||||
extern size_t (*device_writeraw)(void*, const char*, size_t);
|
||||
extern size_t (*device_width)(void*);
|
||||
extern size_t (*device_height)(void*);
|
||||
extern void (*device_get_cursor)(void*, size_t*, size_t*);
|
||||
|
@ -55,6 +56,7 @@ extern bool (*emergency_device_is_impaired)(void*);
|
|||
extern bool (*emergency_device_recoup)(void*);
|
||||
extern void (*emergency_device_reset)(void*);
|
||||
extern size_t (*emergency_device_callback)(void*, const char*, size_t);
|
||||
extern size_t (*emergency_device_writeraw)(void*, const char*, size_t);
|
||||
extern size_t (*emergency_device_width)(void*);
|
||||
extern size_t (*emergency_device_height)(void*);
|
||||
extern void (*emergency_device_get_cursor)(void*, size_t*, size_t*);
|
||||
|
@ -98,7 +100,7 @@ inline size_t Print(const char* str)
|
|||
|
||||
inline size_t PrintData(const void* ptr, size_t size)
|
||||
{
|
||||
return device_callback(device_pointer, (const char*) ptr, size);
|
||||
return device_writeraw(device_pointer, (const char*) ptr, size);
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 1, 2)))
|
||||
|
|
|
@ -50,6 +50,10 @@
|
|||
#define PARMRK (1U << 11)
|
||||
|
||||
#define OPOST (1U << 0)
|
||||
#if __USE_SORTIX || __USE_XOPEN
|
||||
#define ONLCR (1U << 1)
|
||||
#define OCRNL (1U << 2)
|
||||
#endif
|
||||
|
||||
#define B0 0
|
||||
#define B50 50
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#define TERMMODE_NONBLOCK (1U << 6) /* ISORTIX_NONBLOCK */
|
||||
#define TERMMODE_TERMIOS (1U << 7) /* !ISORTIX_TERMMODE */
|
||||
#define TERMMODE_DISABLE (1U << 8) /* !CREAD */
|
||||
#define TERMMODE_NOOPOST (1U << 9) /* !OPOST */
|
||||
#define TERMMODE_NOONLCR (1U << 10) /* !ONLCR */
|
||||
#define TERMMODE_OCRNL (1U << 11) /* OCRNL */
|
||||
#define TERMMODE_NORMAL (TERMMODE_UNICODE | TERMMODE_SIGNAL | TERMMODE_UTF8 | \
|
||||
TERMMODE_LINEBUFFER | TERMMODE_ECHO | TERMMODE_TERMIOS)
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ size_t fallback_framebuffer_height = 0;
|
|||
|
||||
TextBufferHandle* device_textbufhandle = NULL;
|
||||
size_t (*device_callback)(void*, const char*, size_t) = NULL;
|
||||
size_t (*device_writeraw)(void*, const char*, size_t) = NULL;
|
||||
size_t (*device_width)(void*) = NULL;
|
||||
size_t (*device_height)(void*) = NULL;
|
||||
void (*device_get_cursor)(void*, size_t*, size_t*) = NULL;
|
||||
|
@ -54,6 +55,7 @@ bool (*emergency_device_is_impaired)(void*) = NULL;
|
|||
bool (*emergency_device_recoup)(void*) = NULL;
|
||||
void (*emergency_device_reset)(void*) = NULL;
|
||||
size_t (*emergency_device_callback)(void*, const char*, size_t) = NULL;
|
||||
size_t (*emergency_device_writeraw)(void*, const char*, size_t) = NULL;
|
||||
size_t (*emergency_device_width)(void*) = NULL;
|
||||
void (*emergency_device_get_cursor)(void*, size_t*, size_t*) = NULL;
|
||||
size_t (*emergency_device_height)(void*) = NULL;
|
||||
|
@ -65,6 +67,11 @@ static size_t PrintToTextTerminal(void* user, const char* str, size_t len)
|
|||
return ((TextTerminal*) user)->Print(str, len);
|
||||
}
|
||||
|
||||
static size_t PrintRawToTextTerminal(void* user, const char* str, size_t len)
|
||||
{
|
||||
return ((TextTerminal*) user)->PrintRaw(str, len);
|
||||
}
|
||||
|
||||
static size_t TextTermWidth(void* user)
|
||||
{
|
||||
return ((TextTerminal*) user)->Width();
|
||||
|
@ -111,6 +118,12 @@ size_t EmergencyPrintToTextTerminal(void* user, const char* str, size_t len)
|
|||
return ((TextTerminal*) user)->EmergencyPrint(str, len);
|
||||
}
|
||||
|
||||
static
|
||||
size_t EmergencyPrintRawToTextTerminal(void* user, const char* str, size_t len)
|
||||
{
|
||||
return ((TextTerminal*) user)->EmergencyPrintRaw(str, len);
|
||||
}
|
||||
|
||||
static size_t EmergencyTextTermWidth(void* user)
|
||||
{
|
||||
return ((TextTerminal*) user)->EmergencyWidth();
|
||||
|
@ -192,6 +205,7 @@ void Init(multiboot_info_t* bootinfo)
|
|||
|
||||
// Register the text terminal as the kernel log.
|
||||
Log::device_callback = PrintToTextTerminal;
|
||||
Log::device_writeraw = PrintRawToTextTerminal;
|
||||
Log::device_width = TextTermWidth;
|
||||
Log::device_height = TextTermHeight;
|
||||
Log::device_get_cursor = TextTermGetCursor;
|
||||
|
@ -204,6 +218,7 @@ void Init(multiboot_info_t* bootinfo)
|
|||
Log::emergency_device_recoup = EmergencyTextTermRecoup;
|
||||
Log::emergency_device_reset = EmergencyTextTermReset;
|
||||
Log::emergency_device_callback = EmergencyPrintToTextTerminal;
|
||||
Log::emergency_device_writeraw = EmergencyPrintRawToTextTerminal;
|
||||
Log::emergency_device_width = EmergencyTextTermWidth;
|
||||
Log::emergency_device_height = EmergencyTextTermHeight;
|
||||
Log::emergency_device_get_cursor = EmergencyTextTermGetCursor;
|
||||
|
|
|
@ -63,6 +63,21 @@ void TextTerminal::Reset()
|
|||
}
|
||||
|
||||
size_t TextTerminal::Print(const char* string, size_t stringlen)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
for ( size_t i = 0; i < stringlen; i++ )
|
||||
{
|
||||
if ( string[i] == '\n' )
|
||||
PutChar(textbuf, '\r');
|
||||
PutChar(textbuf, string[i]);
|
||||
}
|
||||
UpdateCursor(textbuf);
|
||||
textbufhandle->Release(textbuf);
|
||||
return stringlen;
|
||||
}
|
||||
|
||||
size_t TextTerminal::PrintRaw(const char* string, size_t stringlen)
|
||||
{
|
||||
ScopedLock lock(&termlock);
|
||||
TextBuffer* textbuf = textbufhandle->Acquire();
|
||||
|
@ -185,6 +200,25 @@ size_t TextTerminal::EmergencyPrint(const char* string, size_t stringlen)
|
|||
// while it held the terminal lock. The best case is if the terminal lock is
|
||||
// currently unused, which would mean everything is safe.
|
||||
|
||||
TextBuffer* textbuf = textbufhandle->EmergencyAcquire();
|
||||
for ( size_t i = 0; i < stringlen; i++ )
|
||||
{
|
||||
if ( string[i] == '\n' )
|
||||
PutChar(textbuf, '\r');
|
||||
PutChar(textbuf, string[i]);
|
||||
}
|
||||
UpdateCursor(textbuf);
|
||||
textbufhandle->EmergencyRelease(textbuf);
|
||||
return stringlen;
|
||||
}
|
||||
|
||||
size_t TextTerminal::EmergencyPrintRaw(const char* string, size_t stringlen)
|
||||
{
|
||||
// This is during a kernel emergency where preemption has been disabled and
|
||||
// this is the only thread running. Another thread may have been interrupted
|
||||
// while it held the terminal lock. The best case is if the terminal lock is
|
||||
// currently unused, which would mean everything is safe.
|
||||
|
||||
TextBuffer* textbuf = textbufhandle->EmergencyAcquire();
|
||||
for ( size_t i = 0; i < stringlen; i++ )
|
||||
PutChar(textbuf, string[i]);
|
||||
|
@ -271,7 +305,10 @@ void TextTerminal::PutChar(TextBuffer* textbuf, char c)
|
|||
wc = L' ';
|
||||
|
||||
if ( textbuf->Width() <= column )
|
||||
{
|
||||
column = 0;
|
||||
Newline(textbuf);
|
||||
}
|
||||
TextPos pos(column++, line);
|
||||
TextChar tc(wc, vgacolor, ATTR_CHAR | next_attr);
|
||||
textbuf->SetChar(pos, tc);
|
||||
|
@ -286,7 +323,6 @@ void TextTerminal::UpdateCursor(TextBuffer* textbuf)
|
|||
void TextTerminal::Newline(TextBuffer* textbuf)
|
||||
{
|
||||
TextPos pos(column, line);
|
||||
column = 0;
|
||||
if ( line < textbuf->Height()-1 )
|
||||
line++;
|
||||
else
|
||||
|
@ -330,7 +366,10 @@ void TextTerminal::Backspace(TextBuffer* textbuf)
|
|||
void TextTerminal::Tab(TextBuffer* textbuf)
|
||||
{
|
||||
if ( column == textbuf->Width() )
|
||||
{
|
||||
column = 0;
|
||||
Newline(textbuf);
|
||||
}
|
||||
unsigned int count = 8 - (column % 8);
|
||||
for ( unsigned int i = 0; i < count; i++ )
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ public:
|
|||
TextTerminal(TextBufferHandle* textbufhandle);
|
||||
~TextTerminal();
|
||||
size_t Print(const char* string, size_t stringlen);
|
||||
size_t PrintRaw(const char* string, size_t stringlen);
|
||||
size_t Width() const;
|
||||
size_t Height() const;
|
||||
void GetCursor(size_t* column, size_t* row) const;
|
||||
|
@ -44,6 +45,7 @@ public:
|
|||
bool EmergencyRecoup();
|
||||
void EmergencyReset();
|
||||
size_t EmergencyPrint(const char* string, size_t stringlen);
|
||||
size_t EmergencyPrintRaw(const char* string, size_t stringlen);
|
||||
size_t EmergencyWidth() const;
|
||||
size_t EmergencyHeight() const;
|
||||
void EmergencyGetCursor(size_t* column, size_t* row) const;
|
||||
|
|
|
@ -63,7 +63,10 @@ static const unsigned int SUPPORTED_TERMMODES = TERMMODE_KBKEY
|
|||
| TERMMODE_ECHO
|
||||
| TERMMODE_NONBLOCK
|
||||
| TERMMODE_TERMIOS
|
||||
| TERMMODE_DISABLE;
|
||||
| TERMMODE_DISABLE
|
||||
| TERMMODE_NOOPOST
|
||||
| TERMMODE_NOONLCR
|
||||
| TERMMODE_OCRNL;
|
||||
|
||||
static inline bool IsByteUnescaped(unsigned char byte)
|
||||
{
|
||||
|
@ -89,7 +92,7 @@ TTY::TTY(dev_t dev, mode_t mode, uid_t owner, gid_t group)
|
|||
this->stat_gid = group;
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
tio.c_iflag = BRKINT | ICRNL | IXANY | IXON;
|
||||
tio.c_oflag = OPOST;
|
||||
tio.c_oflag = OPOST | ONLCR;
|
||||
tio.c_cflag = CS8 /*| CREAD*/ | HUPCL; // CREAD unset for boot security.
|
||||
tio.c_lflag = ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG;
|
||||
tio.c_cc[VEOF] = CONTROL('D');
|
||||
|
@ -127,6 +130,8 @@ int TTY::settermmode(ioctx_t* /*ctx*/, unsigned int termmode)
|
|||
tcflag_t new_cflag = old_cflag;
|
||||
tcflag_t old_lflag = tio.c_lflag;
|
||||
tcflag_t new_lflag = old_lflag;
|
||||
tcflag_t old_oflag = tio.c_oflag;
|
||||
tcflag_t new_oflag = old_oflag;
|
||||
if ( termmode & TERMMODE_KBKEY )
|
||||
new_lflag |= ISORTIX_KBKEY;
|
||||
else
|
||||
|
@ -163,12 +168,25 @@ int TTY::settermmode(ioctx_t* /*ctx*/, unsigned int termmode)
|
|||
new_cflag |= CREAD;
|
||||
else
|
||||
new_cflag &= ~CREAD;
|
||||
if ( !(termmode & TERMMODE_NOOPOST) )
|
||||
new_oflag |= OPOST;
|
||||
else
|
||||
new_oflag &= ~OPOST;
|
||||
if ( !(termmode & TERMMODE_NOONLCR) )
|
||||
new_oflag |= ONLCR;
|
||||
else
|
||||
new_oflag &= ~ONLCR;
|
||||
if ( termmode & TERMMODE_OCRNL )
|
||||
new_oflag |= OCRNL;
|
||||
else
|
||||
new_oflag &= ~OCRNL;
|
||||
bool oldnoutf8 = old_lflag & ISORTIX_32BIT;
|
||||
bool newnoutf8 = new_lflag & ISORTIX_32BIT;
|
||||
if ( oldnoutf8 != newnoutf8 )
|
||||
memset(&read_ps, 0, sizeof(read_ps));
|
||||
tio.c_cflag = new_cflag;
|
||||
tio.c_lflag = new_lflag;
|
||||
tio.c_oflag = new_oflag;
|
||||
if ( !(tio.c_lflag & ICANON) )
|
||||
CommitLineBuffer();
|
||||
return 0;
|
||||
|
@ -196,6 +214,12 @@ int TTY::gettermmode(ioctx_t* ctx, unsigned int* mode)
|
|||
termmode |= TERMMODE_TERMIOS;
|
||||
if ( !(tio.c_cflag & CREAD) )
|
||||
termmode |= TERMMODE_DISABLE;
|
||||
if ( !(tio.c_oflag & OPOST) )
|
||||
termmode |= TERMMODE_NOOPOST;
|
||||
if ( !(tio.c_oflag & ONLCR) )
|
||||
termmode |= TERMMODE_NOONLCR;
|
||||
if ( tio.c_oflag & OCRNL )
|
||||
termmode |= TERMMODE_OCRNL;
|
||||
if ( !ctx->copy_to_dest(mode, &termmode, sizeof(termmode)) )
|
||||
return -1;
|
||||
return 0;
|
||||
|
@ -418,7 +442,16 @@ void TTY::ProcessByte(unsigned char byte, uint32_t control_unicode)
|
|||
|
||||
if ( tio.c_lflag & ECHO )
|
||||
{
|
||||
if ( IsByteUnescaped(byte) )
|
||||
if ( byte == '\n' )
|
||||
{
|
||||
if ( tio.c_oflag & OPOST && tio.c_oflag & ONLCR )
|
||||
Log::PrintData("\r\n", 2);
|
||||
else if ( tio.c_oflag & OPOST && tio.c_oflag & OCRNL )
|
||||
Log::PrintData("\r", 1);
|
||||
else
|
||||
Log::PrintData("\n", 1);
|
||||
}
|
||||
else if ( IsByteUnescaped(byte) )
|
||||
Log::PrintData(&byte, 1);
|
||||
else
|
||||
Log::PrintF("^%c", CONTROL(byte));
|
||||
|
@ -556,26 +589,59 @@ ssize_t TTY::write(ioctx_t* ctx, const uint8_t* io_buffer, size_t count)
|
|||
if ( tio.c_lflag & TOSTOP && !RequireForeground(SIGTTOU) )
|
||||
return errno = EINTR, -1;
|
||||
// TODO: Add support for ioctx to the kernel log.
|
||||
const size_t BUFFER_SIZE = 64UL;
|
||||
char buffer[BUFFER_SIZE];
|
||||
unsigned char buffer[256];
|
||||
size_t max_incoming = sizeof(buffer);
|
||||
if ( tio.c_oflag & OPOST && tio.c_oflag & ONLCR )
|
||||
max_incoming = sizeof(buffer) / 2;
|
||||
size_t sofar = 0;
|
||||
size_t rounds = 0;
|
||||
while ( sofar < count )
|
||||
{
|
||||
size_t amount = count - sofar;
|
||||
if ( BUFFER_SIZE < amount )
|
||||
amount = BUFFER_SIZE;
|
||||
if ( !ctx->copy_from_src(buffer, io_buffer + sofar, amount) )
|
||||
size_t incoming = count - sofar;
|
||||
if ( max_incoming < incoming )
|
||||
incoming = max_incoming;
|
||||
if ( !ctx->copy_from_src(buffer, io_buffer + sofar, incoming) )
|
||||
return -1;
|
||||
Log::PrintData(buffer, amount);
|
||||
sofar += amount;
|
||||
if ( sofar < count )
|
||||
size_t offset;
|
||||
size_t outgoing;
|
||||
if ( tio.c_oflag & OPOST && tio.c_oflag & ONLCR )
|
||||
{
|
||||
offset = sizeof(buffer);
|
||||
outgoing = incoming;
|
||||
for ( size_t ii = incoming; ii; ii-- )
|
||||
{
|
||||
size_t i = ii - 1;
|
||||
if ( buffer[i] == '\n' )
|
||||
{
|
||||
buffer[--offset] = '\n';
|
||||
buffer[--offset] = '\r';
|
||||
outgoing++;
|
||||
}
|
||||
else
|
||||
buffer[--offset] = buffer[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
outgoing = incoming;
|
||||
if ( tio.c_oflag & OPOST && tio.c_oflag & OCRNL )
|
||||
{
|
||||
for ( size_t i = 0; i < incoming; i++ )
|
||||
if ( buffer[i] == '\r' )
|
||||
buffer[i] = '\n';
|
||||
}
|
||||
}
|
||||
Log::PrintData(buffer + offset, outgoing);
|
||||
sofar += incoming;
|
||||
if ( ++rounds % 16 == 0 )
|
||||
{
|
||||
kthread_mutex_unlock(&termlock);
|
||||
kthread_yield();
|
||||
kthread_mutex_lock(&termlock);
|
||||
if ( Signal::IsPending() )
|
||||
return sofar;
|
||||
}
|
||||
if ( Signal::IsPending() )
|
||||
return sofar;
|
||||
}
|
||||
return (ssize_t) sofar;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue