tty_input_read() was blocking until the whole buffer could be filled - that's

not really standard behaviour...
tty_input_putc() now also releases the reader semaphore if that hasn't been
done before.
tty_input_putc_locked() now does character processing and sends some signals -
not yet complete, though, especially VERASE and VKILL do nothing right now.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9109 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-09-29 12:58:33 +00:00
parent 8b2f07b69e
commit 2ff1ba0dc7

View File

@ -254,7 +254,7 @@ reset_termios(struct termios &termios)
memset(&termios, 0, sizeof(struct termios));
termios.c_iflag = 0;
termios.c_oflag = OPOST;
termios.c_oflag = 0;
termios.c_cflag = B19200 | CS8 | CREAD | HUPCL;
// enable receiver, hang up on last close
termios.c_lflag = 0;
@ -277,7 +277,9 @@ reset_tty(struct tty *tty, int32 index)
tty->open_count = 0;
tty->index = index;
tty->pgrp_id = 0;
// this value prevents any signal of being sent
tty->lock.sem = tty->read_sem = tty->write_sem = -1;
// the semaphores are only created when the TTY is actually in use
@ -296,9 +298,68 @@ tty_output_getc(struct tty *tty, int *_c)
}
/** Processes the input character and puts it into the TTY's input buffer.
* Depending on the termios flags set, signals may be sent, the input
* character changed or removed, etc.
*/
static void
tty_input_putc_locked(struct tty *tty, int c)
{
tcflag_t flags = tty->termios.c_iflag;
// process signals if needed
if ((tty->termios.c_lflag & ISIG) != 0) {
// enable signals, process INTR, QUIT, and SUSP
int signal = -1;
if (c == tty->termios.c_cc[VINTR])
signal = SIGINT;
else if (c == tty->termios.c_cc[VQUIT])
signal = SIGQUIT;
else if (c == tty->termios.c_cc[VSUSP])
// ToDo: what to do here?
signal = -1;
// do we need to deliver a signal?
if (signal != -1) {
// we may have to flush the input buffer
if ((tty->termios.c_lflag & NOFLSH) == 0)
clear_line_buffer(tty->input_buffer);
if (tty->pgrp_id != 0)
send_signal(-tty->pgrp_id, signal);
return;
}
}
// process special canonical input characters
if ((tty->termios.c_lflag & ICANON) != 0) {
// canonical mode, process ERASE and KILL
if (c == tty->termios.c_cc[VERASE]) {
// ToDo: erase one character
return;
} else if (c == tty->termios.c_cc[VKILL]) {
// ToDo: erase line
return;
}
}
// character conversions
if (c == '\n' && (flags & INLCR) != 0) {
// map NL to CR
c = '\r';
} else if (c == '\r') {
if (flags & IGNCR) // ignore CR
return;
if (flags & ICRNL) // map CR to NL
c = '\n';
} if (flags & ISTRIP) // strip the highest bit
c &= 0x7f;
line_buffer_putc(tty->input_buffer, c);
}
@ -312,10 +373,20 @@ tty_input_putc(struct tty *tty, int c)
MutexLocker locker(&tty->lock);
bool wasEmpty = line_buffer_readable(tty->input_buffer) == 0;
tty_input_putc_locked(tty, c);
// If the buffer was empty before, we can now start other readers on it.
// We assume that most of the time more than one character will be written
// using this function, so we don't want to reschedule after every character
if (wasEmpty)
release_sem_etc(tty->read_sem, 1, B_DO_NOT_RESCHEDULE);
// We only wrote one char - we give others the opportunity
// to write if there is still space left in the buffer
if (line_buffer_writable(tty->input_buffer))
release_sem(tty->write_sem);
release_sem_etc(tty->write_sem, 1, B_DO_NOT_RESCHEDULE);
}
@ -434,33 +505,34 @@ tty_input_read(struct tty *tty, void *buffer, size_t *_length, uint32 mode)
{
bool dontBlock = (mode & O_NONBLOCK) != 0;
size_t length = *_length;
size_t bytesLeft = length;
ssize_t bytesRead = 0;
if (length == 0)
return B_OK;
ReaderLocker locker(tty);
while (bytesLeft > 0) {
while (bytesRead == 0) {
status_t status = locker.AcquireReader(dontBlock);
if (status != B_OK) {
*_length -= bytesLeft;
*_length = 0;
return status;
}
ssize_t bytesRead = line_buffer_user_read(tty->input_buffer, (char *)buffer, bytesLeft);
// ToDo: add support for ICANON mode
ssize_t bytesRead = line_buffer_user_read(tty->input_buffer, (char *)buffer, length);
if (bytesRead < B_OK) {
*_length = 0;
locker.ReportRead(0);
return bytesRead;
}
bytesLeft -= bytesRead;
locker.ReportRead(bytesRead);
}
locker.ReportRead(bytesRead);
*_length = bytesRead;
return B_OK;
}