generic/tty: Combine settings structures.
It doesn't make much sense to have separate window sizes, termios, etc. settings for the two halves of a TTY. Moreover, having separate settings which can get out of sync breaks applications, e.g. double-printing in shells. The original TTY driver has unified settings. It seems likely that the settings were separated as part of the locking simplification, however the lock separation was reverted a while back, anyway.
This commit is contained in:
parent
94457adea2
commit
bb57ea897d
@ -64,7 +64,7 @@ dump_tty_struct(struct tty& tty)
|
||||
kprintf(" writer queue:\n");
|
||||
tty.writer_queue.Dump(" ");
|
||||
|
||||
dump_tty_settings(tty.settings);
|
||||
dump_tty_settings(*tty.settings);
|
||||
|
||||
kprintf(" cookies: ");
|
||||
TTYCookieList::Iterator it = tty.cookies.GetIterator();
|
||||
|
@ -506,7 +506,7 @@ WriterLocker::WriterLocker(tty_cookie* sourceCookie)
|
||||
|
||||
// get the echo mode
|
||||
fEcho = (fSource->is_master
|
||||
&& fSource->settings.termios.c_lflag & ECHO) != 0;
|
||||
&& fSource->settings->termios.c_lflag & ECHO) != 0;
|
||||
|
||||
// enqueue ourselves in the respective request queues
|
||||
RecursiveLocker locker(gTTYRequestLock);
|
||||
@ -687,10 +687,10 @@ ReaderLocker::_CheckAvailableBytes() const
|
||||
{
|
||||
// Reading from the slave with canonical input processing enabled means
|
||||
// that we read at max until hitting a line end or EOF.
|
||||
if (!fTTY->is_master && (fTTY->settings.termios.c_lflag & ICANON) != 0) {
|
||||
if (!fTTY->is_master && (fTTY->settings->termios.c_lflag & ICANON) != 0) {
|
||||
return line_buffer_readable_line(fTTY->input_buffer,
|
||||
fTTY->settings.termios.c_cc[VEOL],
|
||||
fTTY->settings.termios.c_cc[VEOF]);
|
||||
fTTY->settings->termios.c_cc[VEOL],
|
||||
fTTY->settings->termios.c_cc[VEOF]);
|
||||
}
|
||||
|
||||
return line_buffer_readable(fTTY->input_buffer);
|
||||
@ -751,36 +751,36 @@ reset_tty_settings(tty_settings& settings)
|
||||
static void
|
||||
tty_input_putc_locked(struct tty* tty, int c)
|
||||
{
|
||||
// process signals if needed
|
||||
const termios& termios = tty->settings->termios;
|
||||
|
||||
if ((tty->settings.termios.c_lflag & ISIG) != 0) {
|
||||
// process signals if needed
|
||||
if ((termios.c_lflag & ISIG) != 0) {
|
||||
// enable signals, process INTR, QUIT, and SUSP
|
||||
int signal = -1;
|
||||
|
||||
if (c == tty->settings.termios.c_cc[VINTR])
|
||||
if (c == termios.c_cc[VINTR])
|
||||
signal = SIGINT;
|
||||
else if (c == tty->settings.termios.c_cc[VQUIT])
|
||||
else if (c == termios.c_cc[VQUIT])
|
||||
signal = SIGQUIT;
|
||||
else if (c == tty->settings.termios.c_cc[VSUSP])
|
||||
else if (c == termios.c_cc[VSUSP])
|
||||
signal = SIGTSTP;
|
||||
|
||||
// do we need to deliver a signal?
|
||||
if (signal != -1) {
|
||||
// we may have to flush the input buffer
|
||||
if ((tty->settings.termios.c_lflag & NOFLSH) == 0)
|
||||
if ((termios.c_lflag & NOFLSH) == 0)
|
||||
clear_line_buffer(tty->input_buffer);
|
||||
|
||||
if (tty->settings.pgrp_id != 0)
|
||||
send_signal(-tty->settings.pgrp_id, signal);
|
||||
if (tty->settings->pgrp_id != 0)
|
||||
send_signal(-tty->settings->pgrp_id, signal);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// process special canonical input characters
|
||||
|
||||
if ((tty->settings.termios.c_lflag & ICANON) != 0) {
|
||||
if ((termios.c_lflag & ICANON) != 0) {
|
||||
// canonical mode, process ERASE and KILL
|
||||
cc_t* controlChars = tty->settings.termios.c_cc;
|
||||
const cc_t* controlChars = termios.c_cc;
|
||||
|
||||
if (c == controlChars[VERASE]) {
|
||||
// erase one character
|
||||
@ -824,10 +824,10 @@ tty_input_putc_locked(struct tty* tty, int c)
|
||||
static int32
|
||||
tty_readable(struct tty* tty)
|
||||
{
|
||||
if (!tty->is_master && (tty->settings.termios.c_lflag & ICANON) != 0) {
|
||||
if (!tty->is_master && (tty->settings->termios.c_lflag & ICANON) != 0) {
|
||||
return line_buffer_readable_line(tty->input_buffer,
|
||||
tty->settings.termios.c_cc[VEOL],
|
||||
tty->settings.termios.c_cc[VEOF]);
|
||||
tty->settings->termios.c_cc[VEOL],
|
||||
tty->settings->termios.c_cc[VEOF]);
|
||||
}
|
||||
|
||||
return line_buffer_readable(tty->input_buffer);
|
||||
@ -906,13 +906,14 @@ static bool
|
||||
process_input_char(struct tty* tty, char c, char* buffer,
|
||||
size_t* _bytesNeeded)
|
||||
{
|
||||
tcflag_t flags = tty->settings.termios.c_iflag;
|
||||
const termios& termios = tty->settings->termios;
|
||||
tcflag_t flags = termios.c_iflag;
|
||||
|
||||
// signals
|
||||
if (tty->settings.termios.c_lflag & ISIG) {
|
||||
if (c == tty->settings.termios.c_cc[VINTR]
|
||||
|| c == tty->settings.termios.c_cc[VQUIT]
|
||||
|| c == tty->settings.termios.c_cc[VSUSP]) {
|
||||
if (termios.c_lflag & ISIG) {
|
||||
if (c == termios.c_cc[VINTR]
|
||||
|| c == termios.c_cc[VQUIT]
|
||||
|| c == termios.c_cc[VSUSP]) {
|
||||
*buffer = c;
|
||||
*_bytesNeeded = 0;
|
||||
return true;
|
||||
@ -920,9 +921,9 @@ process_input_char(struct tty* tty, char c, char* buffer,
|
||||
}
|
||||
|
||||
// canonical input characters
|
||||
if (tty->settings.termios.c_lflag & ICANON) {
|
||||
if (c == tty->settings.termios.c_cc[VERASE]
|
||||
|| c == tty->settings.termios.c_cc[VKILL]) {
|
||||
if (termios.c_lflag & ICANON) {
|
||||
if (c == termios.c_cc[VERASE]
|
||||
|| c == termios.c_cc[VKILL]) {
|
||||
*buffer = c;
|
||||
*_bytesNeeded = 0;
|
||||
return true;
|
||||
@ -961,11 +962,12 @@ static void
|
||||
process_output_char(struct tty* tty, char c, char* buffer,
|
||||
size_t* _bytesWritten, bool echoed)
|
||||
{
|
||||
tcflag_t flags = tty->settings.termios.c_oflag;
|
||||
const termios& termios = tty->settings->termios;
|
||||
tcflag_t flags = termios.c_oflag;
|
||||
|
||||
if (flags & OPOST) {
|
||||
if (echoed && c == tty->settings.termios.c_cc[VERASE]) {
|
||||
if (tty->settings.termios.c_lflag & ECHOE) {
|
||||
if (echoed && c == termios.c_cc[VERASE]) {
|
||||
if (termios.c_lflag & ECHOE) {
|
||||
// ERASE -> BS SPACE BS
|
||||
buffer[0] = CTRL('H');
|
||||
buffer[1] = ' ';
|
||||
@ -973,18 +975,18 @@ process_output_char(struct tty* tty, char c, char* buffer,
|
||||
*_bytesWritten = 3;
|
||||
return;
|
||||
}
|
||||
} else if (echoed && c == tty->settings.termios.c_cc[VKILL]) {
|
||||
if (!(tty->settings.termios.c_lflag & ECHOK)) {
|
||||
} else if (echoed && c == termios.c_cc[VKILL]) {
|
||||
if (!(termios.c_lflag & ECHOK)) {
|
||||
// don't echo KILL
|
||||
*_bytesWritten = 0;
|
||||
return;
|
||||
}
|
||||
} else if (echoed && c == tty->settings.termios.c_cc[VEOF]) {
|
||||
} else if (echoed && c == termios.c_cc[VEOF]) {
|
||||
// don't echo EOF
|
||||
*_bytesWritten = 0;
|
||||
return;
|
||||
} else if (c == '\n') {
|
||||
if (echoed && !(tty->settings.termios.c_lflag & ECHONL)) {
|
||||
if (echoed && !(termios.c_lflag & ECHONL)) {
|
||||
// don't echo NL
|
||||
*_bytesWritten = 0;
|
||||
return;
|
||||
@ -1040,7 +1042,7 @@ tty_write_to_tty_master_unsafe(tty_cookie* sourceCookie, const char* data,
|
||||
if (target->open_count <= 0)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
bool echo = (source->settings.termios.c_lflag & ECHO) != 0;
|
||||
bool echo = (source->settings->termios.c_lflag & ECHO) != 0;
|
||||
|
||||
TRACE(("tty_write_to_tty_master(source = %p, target = %p, "
|
||||
"length = %lu%s)\n", source, target, length,
|
||||
@ -1282,14 +1284,20 @@ tty_create(tty_service_func func, struct tty* master)
|
||||
if (master == NULL) {
|
||||
tty->is_master = true;
|
||||
tty->lock = new(std::nothrow) recursive_lock;
|
||||
if (tty->lock == NULL) {
|
||||
tty->settings = new(std::nothrow) tty_settings;
|
||||
if (tty->lock == NULL || tty->settings == NULL) {
|
||||
delete tty->lock;
|
||||
delete tty->settings;
|
||||
delete tty;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
recursive_lock_init(tty->lock, "tty lock");
|
||||
reset_tty_settings(*tty->settings);
|
||||
} else {
|
||||
tty->is_master = false;
|
||||
tty->lock = master->lock;
|
||||
tty->settings = master->settings;
|
||||
}
|
||||
|
||||
tty->ref_count = 0;
|
||||
@ -1299,8 +1307,6 @@ tty_create(tty_service_func func, struct tty* master)
|
||||
tty->pending_eof = 0;
|
||||
tty->hardware_bits = 0;
|
||||
|
||||
reset_tty_settings(tty->settings);
|
||||
|
||||
if (init_line_buffer(tty->input_buffer, TTY_BUFFER_SIZE) < B_OK) {
|
||||
if (tty->is_master) {
|
||||
recursive_lock_destroy(tty->lock);
|
||||
@ -1325,6 +1331,7 @@ tty_destroy(struct tty* tty)
|
||||
if (tty->is_master) {
|
||||
recursive_lock_destroy(tty->lock);
|
||||
delete tty->lock;
|
||||
delete tty->settings;
|
||||
}
|
||||
|
||||
delete tty;
|
||||
@ -1501,12 +1508,12 @@ tty_read(tty_cookie* cookie, void* _buffer, size_t* _length)
|
||||
ReaderLocker locker(cookie);
|
||||
|
||||
// handle raw mode
|
||||
if ((!tty->is_master) && ((tty->settings.termios.c_lflag & ICANON) == 0)) {
|
||||
if ((!tty->is_master) && ((tty->settings->termios.c_lflag & ICANON) == 0)) {
|
||||
canon = false;
|
||||
if (!dontBlock) {
|
||||
// Non-blocking mode. Handle VMIN and VTIME.
|
||||
bytesNeeded = tty->settings.termios.c_cc[VMIN];
|
||||
bigtime_t vtime = tty->settings.termios.c_cc[VTIME] * 100000;
|
||||
bytesNeeded = tty->settings->termios.c_cc[VMIN];
|
||||
bigtime_t vtime = tty->settings->termios.c_cc[VTIME] * 100000;
|
||||
TRACE(("tty_input_read: icanon vmin %lu, vtime %" B_PRIdBIGTIME
|
||||
"us\n", bytesNeeded, vtime));
|
||||
|
||||
@ -1547,7 +1554,7 @@ tty_read(tty_cookie* cookie, void* _buffer, size_t* _length)
|
||||
bool* hitEOF = canon && tty->pending_eof > 0 ? &_hitEOF : NULL;
|
||||
|
||||
ssize_t bytesRead = line_buffer_user_read(tty->input_buffer, buffer,
|
||||
toRead, tty->settings.termios.c_cc[VEOF], hitEOF);
|
||||
toRead, tty->settings->termios.c_cc[VEOF], hitEOF);
|
||||
if (bytesRead < 0) {
|
||||
status = bytesRead;
|
||||
break;
|
||||
@ -1622,7 +1629,7 @@ tty_control(tty_cookie* cookie, uint32 op, void* buffer, size_t length)
|
||||
|
||||
case TCGETA:
|
||||
TRACE(("tty: get attributes\n"));
|
||||
return user_memcpy(buffer, &tty->settings.termios,
|
||||
return user_memcpy(buffer, &tty->settings->termios,
|
||||
sizeof(struct termios));
|
||||
|
||||
case TCSETA:
|
||||
@ -1631,16 +1638,16 @@ tty_control(tty_cookie* cookie, uint32 op, void* buffer, size_t length)
|
||||
{
|
||||
TRACE(("tty: set attributes (iflag = %" B_PRIx32 ", oflag = %"
|
||||
B_PRIx32 ", cflag = %" B_PRIx32 ", lflag = %" B_PRIx32 ")\n",
|
||||
tty->settings.termios.c_iflag, tty->settings.termios.c_oflag,
|
||||
tty->settings.termios.c_cflag,
|
||||
tty->settings.termios.c_lflag));
|
||||
tty->settings->termios.c_iflag, tty->settings->termios.c_oflag,
|
||||
tty->settings->termios.c_cflag,
|
||||
tty->settings->termios.c_lflag));
|
||||
|
||||
status_t status = user_memcpy(&tty->settings.termios, buffer,
|
||||
status_t status = user_memcpy(&tty->settings->termios, buffer,
|
||||
sizeof(struct termios));
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
tty->service_func(tty, TTYSETMODES, &tty->settings.termios,
|
||||
tty->service_func(tty, TTYSETMODES, &tty->settings->termios,
|
||||
sizeof(struct termios));
|
||||
return status;
|
||||
}
|
||||
@ -1649,25 +1656,25 @@ tty_control(tty_cookie* cookie, uint32 op, void* buffer, size_t length)
|
||||
|
||||
case TIOCGWINSZ:
|
||||
TRACE(("tty: get window size\n"));
|
||||
return user_memcpy(buffer, &tty->settings.window_size,
|
||||
return user_memcpy(buffer, &tty->settings->window_size,
|
||||
sizeof(struct winsize));
|
||||
|
||||
case TIOCSWINSZ:
|
||||
{
|
||||
uint16 oldColumns = tty->settings.window_size.ws_col;
|
||||
uint16 oldRows = tty->settings.window_size.ws_row;
|
||||
uint16 oldColumns = tty->settings->window_size.ws_col;
|
||||
uint16 oldRows = tty->settings->window_size.ws_row;
|
||||
|
||||
TRACE(("tty: set window size\n"));
|
||||
if (user_memcpy(&tty->settings.window_size, buffer,
|
||||
if (user_memcpy(&tty->settings->window_size, buffer,
|
||||
sizeof(struct winsize)) < B_OK) {
|
||||
return B_BAD_ADDRESS;
|
||||
}
|
||||
|
||||
// send a signal only if the window size has changed
|
||||
if ((oldColumns != tty->settings.window_size.ws_col
|
||||
|| oldRows != tty->settings.window_size.ws_row)
|
||||
&& tty->settings.pgrp_id != 0) {
|
||||
send_signal(-tty->settings.pgrp_id, SIGWINCH);
|
||||
if ((oldColumns != tty->settings->window_size.ws_col
|
||||
|| oldRows != tty->settings->window_size.ws_row)
|
||||
&& tty->settings->pgrp_id != 0) {
|
||||
send_signal(-tty->settings->pgrp_id, SIGWINCH);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -1855,7 +1862,7 @@ tty_select(tty_cookie* cookie, uint8 event, uint32 ref, selectsync* sync)
|
||||
// In case input is echoed, we have to check, whether we can
|
||||
// currently can write to our TTY as well.
|
||||
bool echo = (tty->is_master
|
||||
&& tty->settings.termios.c_lflag & ECHO);
|
||||
&& tty->settings->termios.c_lflag & ECHO);
|
||||
|
||||
if (otherTTY->writer_queue.IsEmpty()
|
||||
&& line_buffer_writable(otherTTY->input_buffer) > 0) {
|
||||
|
@ -138,7 +138,7 @@ struct tty {
|
||||
uint32 pending_eof;
|
||||
bool is_master;
|
||||
recursive_lock* lock;
|
||||
tty_settings settings;
|
||||
tty_settings* settings;
|
||||
uint8 hardware_bits;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user