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
|
Displays the terminal reset string, which typically resets the terminal to
|
||||||
its power-on state.
|
its power-on state.
|
||||||
.TP
|
.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]
|
\fB\-\-reverse\fP [\fBon\fP|\fBoff\fP]
|
||||||
Turns reverse video mode on or off. Except on a virtual console,
|
Turns reverse video mode on or off. Except on a virtual console,
|
||||||
.B \-\-reverse off
|
.B \-\-reverse off
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
# include <linux/tiocl.h>
|
# include <linux/tiocl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "all-io.h"
|
||||||
#include "c.h"
|
#include "c.h"
|
||||||
#include "closestream.h"
|
#include "closestream.h"
|
||||||
#include "nls.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,
|
opt_appck_on:1, opt_invsc_on:1, opt_msg_on:1, opt_cl_all:1,
|
||||||
vcterm:1;
|
vcterm:1;
|
||||||
/* Option flags. Set when an option is invoked. */
|
/* 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_linewrap:1, opt_default:1, opt_foreground:1,
|
||||||
opt_background:1, opt_bold:1, opt_blink:1, opt_reverse: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,
|
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(USAGE_OPTIONS, out);
|
||||||
fputs(_(" --term <terminal_name> override TERM environment variable\n"), out);
|
fputs(_(" --term <terminal_name> override TERM environment variable\n"), out);
|
||||||
fputs(_(" --reset reset terminal to power-on state\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(_(" --initialize display init string, and use default settings\n"), out);
|
||||||
fputs(_(" --default use default terminal settings\n"), out);
|
fputs(_(" --default use default terminal settings\n"), out);
|
||||||
fputs(_(" --store save current terminal settings as default\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 {
|
enum {
|
||||||
OPT_TERM = CHAR_MAX + 1,
|
OPT_TERM = CHAR_MAX + 1,
|
||||||
OPT_RESET,
|
OPT_RESET,
|
||||||
|
OPT_RESIZE,
|
||||||
OPT_INITIALIZE,
|
OPT_INITIALIZE,
|
||||||
OPT_CURSOR,
|
OPT_CURSOR,
|
||||||
OPT_REPEAT,
|
OPT_REPEAT,
|
||||||
|
@ -474,6 +477,7 @@ static void parse_option(struct setterm_control *ctl, int ac, char **av)
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{"term", required_argument, NULL, OPT_TERM},
|
{"term", required_argument, NULL, OPT_TERM},
|
||||||
{"reset", no_argument, NULL, OPT_RESET},
|
{"reset", no_argument, NULL, OPT_RESET},
|
||||||
|
{"resize", no_argument, NULL, OPT_RESIZE},
|
||||||
{"initialize", no_argument, NULL, OPT_INITIALIZE},
|
{"initialize", no_argument, NULL, OPT_INITIALIZE},
|
||||||
{"cursor", required_argument, NULL, OPT_CURSOR},
|
{"cursor", required_argument, NULL, OPT_CURSOR},
|
||||||
{"repeat", required_argument, NULL, OPT_REPEAT},
|
{"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:
|
case OPT_RESET:
|
||||||
ctl->opt_reset = set_opt_flag(ctl->opt_reset);
|
ctl->opt_reset = set_opt_flag(ctl->opt_reset);
|
||||||
break;
|
break;
|
||||||
|
case OPT_RESIZE:
|
||||||
|
ctl->opt_resize = set_opt_flag(ctl->opt_resize);
|
||||||
|
break;
|
||||||
case OPT_INITIALIZE:
|
case OPT_INITIALIZE:
|
||||||
ctl->opt_initialize = set_opt_flag(ctl->opt_initialize);
|
ctl->opt_initialize = set_opt_flag(ctl->opt_initialize);
|
||||||
break;
|
break;
|
||||||
|
@ -815,6 +822,104 @@ static int vc_only(struct setterm_control *ctl, const char *err)
|
||||||
return ctl->vcterm;
|
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)
|
static void perform_sequence(struct setterm_control *ctl)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
@ -823,6 +928,11 @@ static void perform_sequence(struct setterm_control *ctl)
|
||||||
if (ctl->opt_reset)
|
if (ctl->opt_reset)
|
||||||
putp(ti_entry("rs1"));
|
putp(ti_entry("rs1"));
|
||||||
|
|
||||||
|
/* -resize. */
|
||||||
|
if (ctl->opt_resize)
|
||||||
|
if (resizetty())
|
||||||
|
warnx(_("reset failed"));
|
||||||
|
|
||||||
/* -initialize. */
|
/* -initialize. */
|
||||||
if (ctl->opt_initialize)
|
if (ctl->opt_initialize)
|
||||||
putp(ti_entry("is2"));
|
putp(ti_entry("is2"));
|
||||||
|
|
Loading…
Reference in New Issue