exec: Add TTYRows and TTYColumns properties to set TTY dimensions

This commit is contained in:
Daan De Meyer 2021-10-28 16:26:50 +01:00
parent b4bf9007cb
commit 51462135fb
17 changed files with 171 additions and 6 deletions

View file

@ -139,6 +139,8 @@ All execution-related settings are available for transient units.
✓ TTYReset=
✓ TTYVHangup=
✓ TTYVTDisallocate=
✓ TTYRows=
✓ TTYColumns=
✓ SyslogIdentifier=
✓ SyslogFacility=
✓ SyslogLevel=

View file

@ -2689,6 +2689,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@ -3230,6 +3234,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property TTYVTDisallocate is not documented!-->
<!--property TTYRows is not documented!-->
<!--property TTYColumns is not documented!-->
<!--property SyslogPriority is not documented!-->
<!--property SyslogIdentifier is not documented!-->
@ -3822,6 +3830,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="TTYVTDisallocate"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYRows"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYColumns"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogPriority"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogIdentifier"/>
@ -4550,6 +4562,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@ -5117,6 +5133,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property TTYVTDisallocate is not documented!-->
<!--property TTYRows is not documented!-->
<!--property TTYColumns is not documented!-->
<!--property SyslogPriority is not documented!-->
<!--property SyslogIdentifier is not documented!-->
@ -5705,6 +5725,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="TTYVTDisallocate"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYRows"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYColumns"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogPriority"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogIdentifier"/>
@ -6323,6 +6347,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@ -6818,6 +6846,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property TTYVTDisallocate is not documented!-->
<!--property TTYRows is not documented!-->
<!--property TTYColumns is not documented!-->
<!--property SyslogPriority is not documented!-->
<!--property SyslogIdentifier is not documented!-->
@ -7324,6 +7356,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="TTYVTDisallocate"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYRows"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYColumns"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogPriority"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogIdentifier"/>
@ -8063,6 +8099,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@ -8544,6 +8584,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property TTYVTDisallocate is not documented!-->
<!--property TTYRows is not documented!-->
<!--property TTYColumns is not documented!-->
<!--property SyslogPriority is not documented!-->
<!--property SyslogIdentifier is not documented!-->
@ -9036,6 +9080,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="TTYVTDisallocate"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYRows"/>
<variablelist class="dbus-property" generated="True" extra-ref="TTYColumns"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogPriority"/>
<variablelist class="dbus-property" generated="True" extra-ref="SyslogIdentifier"/>

View file

@ -2950,6 +2950,14 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
<varname>TTYPath=</varname> before and after execution. Defaults to <literal>no</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>TTYRows=</varname></term>
<term><varname>TTYColumns=</varname></term>
<listitem><para>Configure the size of the TTY specified with <varname>TTYPath=</varname>. If unset or
set to the empty string, the kernel default is used.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>TTYVTDisallocate=</varname></term>

View file

@ -857,6 +857,39 @@ unsigned lines(void) {
return cached_lines;
}
int terminal_set_size_fd(int fd, const char *ident, unsigned rows, unsigned cols) {
struct winsize ws;
if (rows == UINT_MAX && cols == UINT_MAX)
return 0;
if (ioctl(fd, TIOCGWINSZ, &ws) < 0)
return log_debug_errno(errno,
"TIOCGWINSZ ioctl for getting %s size failed, not setting terminal size: %m",
ident ?: "TTY");
if (rows == UINT_MAX)
rows = ws.ws_row;
else if (rows > USHRT_MAX)
rows = USHRT_MAX;
if (cols == UINT_MAX)
cols = ws.ws_col;
else if (cols > USHRT_MAX)
cols = USHRT_MAX;
if (rows == ws.ws_row && cols == ws.ws_col)
return 0;
ws.ws_row = rows;
ws.ws_col = cols;
if (ioctl(fd, TIOCSWINSZ, &ws) < 0)
return log_debug_errno(errno, "TIOCSWINSZ ioctl for setting %s size failed: %m", ident ?: "TTY");
return 0;
}
/* intended to be used as a SIGWINCH sighandler */
void columns_lines_cache_reset(int signum) {
cached_columns = 0;

View file

@ -120,6 +120,8 @@ int release_terminal(void);
int terminal_vhangup_fd(int fd);
int terminal_vhangup(const char *name);
int terminal_set_size_fd(int fd, const char *ident, unsigned rows, unsigned cols);
int chvt(int vt);
int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);

View file

@ -1230,6 +1230,8 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYRows", "q", bus_property_get_unsigned, offsetof(ExecContext, tty_rows), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("TTYColumns", "q", bus_property_get_unsigned, offsetof(ExecContext, tty_cols), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
@ -1860,6 +1862,12 @@ int bus_exec_context_set_transient_property(
if (streq(name, "TTYVTDisallocate"))
return bus_set_transient_bool(u, name, &c->tty_vt_disallocate, message, flags, error);
if (streq(name, "TTYRows"))
return bus_set_transient_unsigned(u, name, &c->tty_rows, message, flags, error);
if (streq(name, "TTYColumns"))
return bus_set_transient_unsigned(u, name, &c->tty_cols, message, flags, error);
if (streq(name, "PrivateTmp"))
return bus_set_transient_bool(u, name, &c->private_tmp, message, flags, error);

View file

@ -213,6 +213,9 @@ static void exec_context_tty_reset(const ExecContext *context, const ExecParamet
(void) reset_terminal(path);
}
if (p && p->stdin_fd >= 0)
(void) terminal_set_size_fd(p->stdin_fd, path, context->tty_rows, context->tty_cols);
if (context->tty_vt_disallocate && path)
(void) vt_disallocate(path);
}
@ -466,6 +469,7 @@ static int setup_input(
const int named_iofds[static 3]) {
ExecInput i;
int r;
assert(context);
assert(params);
@ -479,6 +483,7 @@ static int setup_input(
if (isatty(STDIN_FILENO)) {
(void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
(void) reset_terminal_fd(STDIN_FILENO, true);
(void) terminal_set_size_fd(STDIN_FILENO, NULL, context->tty_rows, context->tty_cols);
}
return STDIN_FILENO;
@ -504,6 +509,10 @@ static int setup_input(
if (fd < 0)
return fd;
r = terminal_set_size_fd(fd, exec_context_tty_path(context), context->tty_rows, context->tty_cols);
if (r < 0)
return r;
return move_fd(fd, STDIN_FILENO, false);
}
@ -757,6 +766,7 @@ static int chown_terminal(int fd, uid_t uid) {
}
static int setup_confirm_stdio(
const ExecContext *context,
const char *vc,
int *ret_saved_stdin,
int *ret_saved_stdout) {
@ -787,6 +797,10 @@ static int setup_confirm_stdio(
if (r < 0)
return r;
r = terminal_set_size_fd(fd, vc, context->tty_rows, context->tty_cols);
if (r < 0)
return r;
r = rearrange_stdio(fd, fd, STDERR_FILENO); /* Invalidates 'fd' also on failure */
TAKE_FD(fd);
if (r < 0)
@ -848,13 +862,13 @@ enum {
CONFIRM_EXECUTE = 1,
};
static int ask_for_confirmation(const char *vc, Unit *u, const char *cmdline) {
static int ask_for_confirmation(const ExecContext *context, const char *vc, Unit *u, const char *cmdline) {
int saved_stdout = -1, saved_stdin = -1, r;
_cleanup_free_ char *e = NULL;
char c;
/* For any internal errors, assume a positive response. */
r = setup_confirm_stdio(vc, &saved_stdin, &saved_stdout);
r = setup_confirm_stdio(context, vc, &saved_stdin, &saved_stdout);
if (r < 0) {
write_confirm_error(r, vc, u);
return CONFIRM_EXECUTE;
@ -3994,7 +4008,7 @@ static int exec_child(
return log_oom();
}
r = ask_for_confirmation(vc, unit, cmdline);
r = ask_for_confirmation(context, vc, unit, cmdline);
if (r != CONFIRM_EXECUTE) {
if (r == CONFIRM_PRETEND_SUCCESS) {
*exit_status = EXIT_SUCCESS;
@ -5066,6 +5080,8 @@ void exec_context_init(ExecContext *c) {
#if HAVE_SECCOMP
c->syscall_errno = SECCOMP_ERROR_NUMBER_KILL;
#endif
c->tty_rows = UINT_MAX;
c->tty_cols = UINT_MAX;
numa_policy_reset(&c->numa_policy);
}
@ -5705,11 +5721,15 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
"%sTTYPath: %s\n"
"%sTTYReset: %s\n"
"%sTTYVHangup: %s\n"
"%sTTYVTDisallocate: %s\n",
"%sTTYVTDisallocate: %s\n"
"%sTTYRows: %u\n"
"%sTTYColumns: %u\n",
prefix, c->tty_path,
prefix, yes_no(c->tty_reset),
prefix, yes_no(c->tty_vhangup),
prefix, yes_no(c->tty_vt_disallocate));
prefix, yes_no(c->tty_vt_disallocate),
prefix, c->tty_rows,
prefix, c->tty_cols);
if (IN_SET(c->std_output,
EXEC_OUTPUT_KMSG,

View file

@ -232,6 +232,9 @@ struct ExecContext {
bool tty_vhangup;
bool tty_vt_disallocate;
unsigned tty_rows;
unsigned tty_cols;
bool ignore_sigpipe;
ExecKeyringMode keyring_mode;

View file

@ -41,6 +41,8 @@
{{type}}.TTYReset, config_parse_bool, 0, offsetof({{type}}, exec_context.tty_reset)
{{type}}.TTYVHangup, config_parse_bool, 0, offsetof({{type}}, exec_context.tty_vhangup)
{{type}}.TTYVTDisallocate, config_parse_bool, 0, offsetof({{type}}, exec_context.tty_vt_disallocate)
{{type}}.TTYRows, config_parse_tty_size, 0, offsetof({{type}}, exec_context.tty_rows)
{{type}}.TTYColumns, config_parse_tty_size, 0, offsetof({{type}}, exec_context.tty_cols)
{{type}}.SyslogIdentifier, config_parse_unit_string_printf, 0, offsetof({{type}}, exec_context.syslog_identifier)
{{type}}.SyslogFacility, config_parse_log_facility, 0, offsetof({{type}}, exec_context.syslog_priority)
{{type}}.SyslogLevel, config_parse_log_level, 0, offsetof({{type}}, exec_context.syslog_priority)

View file

@ -6494,3 +6494,29 @@ int config_parse_watchdog_sec(
return 0;
}
int config_parse_tty_size(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
unsigned *sz = data;
assert(filename);
assert(lvalue);
assert(rvalue);
if (isempty(rvalue)) {
*sz = UINT_MAX;
return 0;
}
return config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, data, userdata);
}

View file

@ -148,6 +148,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_bpf_foreign_program);
CONFIG_PARSER_PROTOTYPE(config_parse_cgroup_socket_bind);
CONFIG_PARSER_PROTOTYPE(config_parse_restrict_network_interfaces);
CONFIG_PARSER_PROTOTYPE(config_parse_watchdog_sec);
CONFIG_PARSER_PROTOTYPE(config_parse_tty_size);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);

View file

@ -1022,7 +1022,9 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
if (streq(field, "LogRateLimitIntervalSec"))
return bus_append_parse_sec_rename(m, field, eq);
if (streq(field, "LogRateLimitBurst"))
if (STR_IN_SET(field, "LogRateLimitBurst",
"TTYRows",
"TTYColumns"))
return bus_append_safe_atou(m, field, eq);
if (streq(field, "MountFlags"))

View file

@ -931,6 +931,8 @@ TTYPath=
TTYReset=
TTYVHangup=
TTYVTDisallocate=
TTYRows=
TTYColumns=
TemporaryFileSystem=
TimerSlackNSec=
TrustedCertificateFile=

View file

@ -195,6 +195,8 @@ TTYPath=
TTYReset=
TTYVHangup=
TTYVTDisallocate=
TTYRows=
TTYColumns=
TasksAccounting=
TasksMax=
TemporaryFileSystem=

View file

@ -332,6 +332,8 @@ TTYPath=
TTYReset=
TTYVHangup=
TTYVTDisallocate=
TTYRows=
TTYColumns=
TasksAccounting=
TasksMax=
TemporaryFileSystem=

View file

@ -243,6 +243,8 @@ TTYPath=
TTYReset=
TTYVHangup=
TTYVTDisallocate=
TTYRows=
TTYColumns=
TasksAccounting=
TasksMax=
TemporaryFileSystem=

View file

@ -191,6 +191,8 @@ TTYPath=
TTYReset=
TTYVHangup=
TTYVTDisallocate=
TTYRows=
TTYColumns=
TasksAccounting=
TasksMax=
TemporaryFileSystem=