]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
exec: Add TTYRows and TTYColumns properties to set TTY dimensions 21171/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Thu, 28 Oct 2021 15:26:50 +0000 (16:26 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Fri, 5 Nov 2021 21:32:14 +0000 (21:32 +0000)
17 files changed:
docs/TRANSIENT-SETTINGS.md
man/org.freedesktop.systemd1.xml
man/systemd.exec.xml
src/basic/terminal-util.c
src/basic/terminal-util.h
src/core/dbus-execute.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.in
src/core/load-fragment.c
src/core/load-fragment.h
src/shared/bus-unit-util.c
test/fuzz/fuzz-unit-file/directives-all.service
test/fuzz/fuzz-unit-file/directives.mount
test/fuzz/fuzz-unit-file/directives.service
test/fuzz/fuzz-unit-file/directives.socket
test/fuzz/fuzz-unit-file/directives.swap

index 218a43c6b7cd5fe6046e61bc6d7ddb188da1ca2c..b90aaa702e24fd6a6ea5e0354782448ec9392af1 100644 (file)
@@ -139,6 +139,8 @@ All execution-related settings are available for transient units.
 ✓ TTYReset=
 ✓ TTYVHangup=
 ✓ TTYVTDisallocate=
+✓ TTYRows=
+✓ TTYColumns=
 ✓ SyslogIdentifier=
 ✓ SyslogFacility=
 ✓ SyslogLevel=
index c9f71a6dca84638f3345b9e81260ef20ad0c23f9..93f2c90280303d75d868ca5db8b282c7ec8c70bc 100644 (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"/>
index 83a23ca9a5db3480b6772051dda20162e0143f2a..c9cae4b9d361bf51366db03c953ae56b507275b3 100644 (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>
 
index 33743f8c4d2374d76fd1d1387740b9b40b09a015..5b8db550527f29e51c3204d28a48b6fa50edc8c2 100644 (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;
index d327627b20dd4859b1714ab15eaa26b63746f60b..ce454bc1aef544edeb16f39028456e67dd01ef9e 100644 (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);
index 3645e680fe52ed84280e92a4ef79366fc1116a9a..afb2d8f10f2db62ad0f48d65f140ca0495fc41bb 100644 (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);
 
index 26f847c1b0131c976f7cff11d27b26e8f7bfb1f4..425e3e5a37cd26281799ed2a8e720f7c9df0b971 100644 (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,
index 18a4316d01c924baf7f5c141f7fda0b5bc3fc385..b0da375def71d40a6adfaee1e4d5862ac9a43717 100644 (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;
index 5ecba47e311044eb811a32b35f391ff4700c74ea..5315d2da885542e5a6a611f391c19c7e816229c3 100644 (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)
index 62cadaf2286ff2510cc4e60d8913e34f872839b0..8cf821cd2283d3251cec054e7b401f713ec52d56 100644 (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);
+}
index 9ff550410f67acc9e39b7e05e17364606f529131..ab2a0393fc889e1e560166f6a286f424c57eb3fd 100644 (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);
index dbd33420be3f19a94f84b9a7ef8061632ae97c91..d1068440f7c7c8d6ead4e405a37019fd3101d57c 100644 (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"))
index 494c7545e48e10c6e08e42888c59a026b9b039a0..37a68708f70ae214833127202dc7a68d6c2ae927 100644 (file)
@@ -931,6 +931,8 @@ TTYPath=
 TTYReset=
 TTYVHangup=
 TTYVTDisallocate=
+TTYRows=
+TTYColumns=
 TemporaryFileSystem=
 TimerSlackNSec=
 TrustedCertificateFile=
index a7ee579a9a3ca2cdc10edb0680127893a014c223..67421444cca0b3e080369c074adfb80f264c4759 100644 (file)
@@ -195,6 +195,8 @@ TTYPath=
 TTYReset=
 TTYVHangup=
 TTYVTDisallocate=
+TTYRows=
+TTYColumns=
 TasksAccounting=
 TasksMax=
 TemporaryFileSystem=
index 4615a2229ac68b78927495c0501f8a13f5a80cdc..d2e2a120a0a31e0177872bb4d5516723d321fc76 100644 (file)
@@ -332,6 +332,8 @@ TTYPath=
 TTYReset=
 TTYVHangup=
 TTYVTDisallocate=
+TTYRows=
+TTYColumns=
 TasksAccounting=
 TasksMax=
 TemporaryFileSystem=
index df641429820ef32eccdf76ea4ebbf8139a1c525b..865fd83adc50c0da88aff8714c2b4dd7e2756edf 100644 (file)
@@ -243,6 +243,8 @@ TTYPath=
 TTYReset=
 TTYVHangup=
 TTYVTDisallocate=
+TTYRows=
+TTYColumns=
 TasksAccounting=
 TasksMax=
 TemporaryFileSystem=
index 1dfdffb379dabe1401ec2fa5e7046c4e274c985a..f538ba8b6095b4281df2f62268512e16fa246422 100644 (file)
@@ -191,6 +191,8 @@ TTYPath=
 TTYReset=
 TTYVHangup=
 TTYVTDisallocate=
+TTYRows=
+TTYColumns=
 TasksAccounting=
 TasksMax=
 TemporaryFileSystem=