Merge branch 'setterm' of git://github.com/kerolasa/lelux-utiliteetit
* 'setterm' of git://github.com/kerolasa/lelux-utiliteetit: setterm: add --resize option
This commit is contained in:
commit
912885d012
|
@ -228,6 +228,13 @@ Turns keyboard repeat on or off.
|
|||
Displays the terminal reset string, which typically resets the terminal to
|
||||
its power-on state.
|
||||
.TP
|
||||
\fB\-\-resize\fP
|
||||
Reset terminal size by assessing maximum row and column. This is useful
|
||||
when actual geometry and kernel terminal driver are not in sync. Most
|
||||
notable use case is with serial consoles, that do not use
|
||||
.BR ioctl (3)
|
||||
but just byte streams and breaks.
|
||||
.TP
|
||||
\fB\-\-reverse\fP [\fBon\fP|\fBoff\fP]
|
||||
Turns reverse video mode on or off. Except on a virtual console,
|
||||
.B \-\-reverse off
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
# include <linux/tiocl.h>
|
||||
#endif
|
||||
|
||||
#include "all-io.h"
|
||||
#include "c.h"
|
||||
#include "closestream.h"
|
||||
#include "nls.h"
|
||||
|
@ -182,7 +183,7 @@ struct setterm_control {
|
|||
opt_appck_on:1, opt_invsc_on:1, opt_msg_on:1, opt_cl_all:1,
|
||||
vcterm:1;
|
||||
/* Option flags. Set when an option is invoked. */
|
||||
uint64_t opt_term:1, opt_reset:1, opt_initialize:1, opt_cursor:1,
|
||||
uint64_t opt_term:1, opt_reset:1, opt_resize:1, opt_initialize:1, opt_cursor:1,
|
||||
opt_linewrap:1, opt_default:1, opt_foreground:1,
|
||||
opt_background:1, opt_bold:1, opt_blink:1, opt_reverse:1,
|
||||
opt_underline:1, opt_store:1, opt_clear:1, opt_blank:1,
|
||||
|
@ -385,6 +386,7 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
|
|||
fputs(USAGE_OPTIONS, out);
|
||||
fputs(_(" --term <terminal_name> override TERM environment variable\n"), out);
|
||||
fputs(_(" --reset reset terminal to power-on state\n"), out);
|
||||
fputs(_(" --resize reset terminal rows and columns\n"), out);
|
||||
fputs(_(" --initialize display init string, and use default settings\n"), out);
|
||||
fputs(_(" --default use default terminal settings\n"), out);
|
||||
fputs(_(" --store save current terminal settings as default\n"), out);
|
||||
|
@ -437,6 +439,7 @@ static void parse_option(struct setterm_control *ctl, int ac, char **av)
|
|||
enum {
|
||||
OPT_TERM = CHAR_MAX + 1,
|
||||
OPT_RESET,
|
||||
OPT_RESIZE,
|
||||
OPT_INITIALIZE,
|
||||
OPT_CURSOR,
|
||||
OPT_REPEAT,
|
||||
|
@ -474,6 +477,7 @@ static void parse_option(struct setterm_control *ctl, int ac, char **av)
|
|||
static const struct option longopts[] = {
|
||||
{"term", required_argument, NULL, OPT_TERM},
|
||||
{"reset", no_argument, NULL, OPT_RESET},
|
||||
{"resize", no_argument, NULL, OPT_RESIZE},
|
||||
{"initialize", no_argument, NULL, OPT_INITIALIZE},
|
||||
{"cursor", required_argument, NULL, OPT_CURSOR},
|
||||
{"repeat", required_argument, NULL, OPT_REPEAT},
|
||||
|
@ -527,6 +531,9 @@ static void parse_option(struct setterm_control *ctl, int ac, char **av)
|
|||
case OPT_RESET:
|
||||
ctl->opt_reset = set_opt_flag(ctl->opt_reset);
|
||||
break;
|
||||
case OPT_RESIZE:
|
||||
ctl->opt_resize = set_opt_flag(ctl->opt_resize);
|
||||
break;
|
||||
case OPT_INITIALIZE:
|
||||
ctl->opt_initialize = set_opt_flag(ctl->opt_initialize);
|
||||
break;
|
||||
|
@ -815,6 +822,104 @@ static int vc_only(struct setterm_control *ctl, const char *err)
|
|||
return ctl->vcterm;
|
||||
}
|
||||
|
||||
static void tty_raw(struct termios *saved_attributes, int *saved_fl)
|
||||
{
|
||||
struct termios tattr;
|
||||
|
||||
fcntl(STDIN_FILENO, F_GETFL, saved_fl);
|
||||
tcgetattr(STDIN_FILENO, saved_attributes);
|
||||
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
|
||||
memcpy(&tattr, saved_attributes, sizeof(struct termios));
|
||||
tattr.c_lflag &= ~(ICANON | ECHO);
|
||||
tattr.c_cc[VMIN] = 1;
|
||||
tattr.c_cc[VTIME] = 0;
|
||||
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr);
|
||||
}
|
||||
|
||||
static void tty_restore(struct termios *saved_attributes, int *saved_fl)
|
||||
{
|
||||
fcntl(STDIN_FILENO, F_SETFL, *saved_fl);
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, saved_attributes);
|
||||
}
|
||||
|
||||
static int select_wait(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set set;
|
||||
int ret;
|
||||
|
||||
FD_ZERO(&set);
|
||||
FD_SET(STDIN_FILENO, &set);
|
||||
tv.tv_sec = 10;
|
||||
tv.tv_usec = 0;
|
||||
while ((ret = select(1, &set, NULL, NULL, &tv)) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
err(EXIT_FAILURE, _("select failed"));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int resizetty(void)
|
||||
{
|
||||
/*
|
||||
* \e7 Save current state (cursor coordinates, attributes,
|
||||
* character sets pointed at by G0, G1).
|
||||
* \e[r Set scrolling region; parameters are top and bottom row.
|
||||
* \e[32766E Move cursor down 32766 (INT16_MAX - 1) rows.
|
||||
* \e[32766C Move cursor right 32766 columns.
|
||||
* \e[6n Report cursor position.
|
||||
* \e8 Restore state most recently saved by \e7.
|
||||
*/
|
||||
static const char *getpos = "\e7\e[r\e[32766E\e[32766C\e[6n\e8";
|
||||
char retstr[32];
|
||||
int row, col;
|
||||
size_t pos;
|
||||
ssize_t rc;
|
||||
struct winsize ws;
|
||||
struct termios saved_attributes;
|
||||
int saved_fl;
|
||||
|
||||
if (!isatty(STDIN_FILENO))
|
||||
errx(EXIT_FAILURE, _("stdin does not refer to a terminal"));
|
||||
|
||||
tty_raw(&saved_attributes, &saved_fl);
|
||||
if (write_all(STDIN_FILENO, getpos, strlen(getpos)) < 0) {
|
||||
warn(_("write failed"));
|
||||
tty_restore(&saved_attributes, &saved_fl);
|
||||
return 1;
|
||||
}
|
||||
for (pos = 0; pos < sizeof(retstr) - 1;) {
|
||||
if (0 == select_wait())
|
||||
break;
|
||||
if ((rc =
|
||||
read(STDIN_FILENO, retstr + pos,
|
||||
sizeof(retstr) - 1 - pos)) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
warn(_("read failed"));
|
||||
tty_restore(&saved_attributes, &saved_fl);
|
||||
return 1;
|
||||
}
|
||||
pos += rc;
|
||||
if (retstr[pos - 1] == 'R')
|
||||
break;
|
||||
}
|
||||
retstr[pos] = 0;
|
||||
tty_restore(&saved_attributes, &saved_fl);
|
||||
rc = sscanf(retstr, "\033[%d;%dR", &row, &col);
|
||||
if (rc != 2) {
|
||||
warnx(_("invalid cursor position: %s"), retstr);
|
||||
return 1;
|
||||
}
|
||||
memset(&ws, 0, sizeof(struct winsize));
|
||||
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
|
||||
ws.ws_row = row;
|
||||
ws.ws_col = col;
|
||||
ioctl(STDIN_FILENO, TIOCSWINSZ, &ws);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void perform_sequence(struct setterm_control *ctl)
|
||||
{
|
||||
int result;
|
||||
|
@ -823,6 +928,11 @@ static void perform_sequence(struct setterm_control *ctl)
|
|||
if (ctl->opt_reset)
|
||||
putp(ti_entry("rs1"));
|
||||
|
||||
/* -resize. */
|
||||
if (ctl->opt_resize)
|
||||
if (resizetty())
|
||||
warnx(_("reset failed"));
|
||||
|
||||
/* -initialize. */
|
||||
if (ctl->opt_initialize)
|
||||
putp(ti_entry("is2"));
|
||||
|
|
Loading…
Reference in New Issue