]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ptyfwd: optionally update window title if we are running a ptyfwd session
authorLennart Poettering <lennart@poettering.net>
Thu, 1 Feb 2024 09:07:30 +0000 (10:07 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 9 Feb 2024 17:27:01 +0000 (18:27 +0100)
src/basic/terminal-util.h
src/shared/ptyfwd.c
src/shared/ptyfwd.h

index 4822917f28fe38155abaea1e06f024e1f1a6a65b..2aed260526a66fed4ec6b4e00e9ee2245cf348e1 100644 (file)
 /* Set cursor to top left corner and clear screen */
 #define ANSI_HOME_CLEAR "\x1B[H\x1B[2J"
 
+/* Push/pop a window title off the stack of window titles */
+#define ANSI_WINDOW_TITLE_PUSH "\x1b[22;2t"
+#define ANSI_WINDOW_TITLE_POP "\x1b[23;2t"
+
 bool isatty_safe(int fd);
 
 int reset_terminal_fd(int fd, bool switch_to_text);
index 3214749595892144a7886ee736b785b323266ddc..f2e5fbb0adc78e68999eebca9bac20210b1599dd 100644 (file)
@@ -92,6 +92,8 @@ struct PTYForward {
         char *background_color;
         AnsiColorState ansi_color_state;
         char *csi_sequence;
+
+        char *title;
 };
 
 #define ESCAPE_USEC (1*USEC_PER_SEC)
@@ -115,9 +117,13 @@ static void pty_forward_disconnect(PTYForward *f) {
                 /* STDIN/STDOUT should not be non-blocking normally, so let's reset it */
                 (void) fd_nonblock(f->output_fd, false);
 
-                if (colors_enabled())
+                if (colors_enabled()) {
                         (void) loop_write(f->output_fd, ANSI_NORMAL ANSI_ERASE_TO_END_OF_SCREEN, SIZE_MAX);
 
+                        if (f->title)
+                                (void) loop_write(f->output_fd, ANSI_WINDOW_TITLE_POP, SIZE_MAX);
+                }
+
                 if (f->close_output_fd)
                         f->output_fd = safe_close(f->output_fd);
         }
@@ -478,17 +484,28 @@ static int shovel(PTYForward *f) {
 
         assert(f);
 
-        if (f->out_buffer_size == 0 && f->background_color) {
-                /* Erase the first line when we start */
-                f->out_buffer = background_color_sequence(f);
-                if (!f->out_buffer)
-                        return pty_forward_done(f, log_oom());
+        if (f->out_buffer_size == 0) {
+                if (f->background_color) {
+                        /* Erase the first line when we start */
+                        f->out_buffer = background_color_sequence(f);
+                        if (!f->out_buffer)
+                                return pty_forward_done(f, log_oom());
 
-                if (!strextend(&f->out_buffer, ANSI_ERASE_TO_END_OF_LINE))
-                        return pty_forward_done(f, log_oom());
+                        if (!strextend(&f->out_buffer, ANSI_ERASE_TO_END_OF_LINE))
+                                return pty_forward_done(f, log_oom());
+                }
 
-                f->out_buffer_full = strlen(f->out_buffer);
-                f->out_buffer_size = MALLOC_SIZEOF_SAFE(f->out_buffer);
+                if (f->title) {
+                        if (!strextend(&f->out_buffer,
+                                       ANSI_WINDOW_TITLE_PUSH
+                                       "\x1b]2;", f->title, "\a"))
+                                return pty_forward_done(f, log_oom());
+                }
+
+                if (f->out_buffer) {
+                        f->out_buffer_full = strlen(f->out_buffer);
+                        f->out_buffer_size = MALLOC_SIZEOF_SAFE(f->out_buffer);
+                }
         }
 
         if (f->out_buffer_size < LINE_MAX) {
@@ -855,6 +872,7 @@ PTYForward *pty_forward_free(PTYForward *f) {
                 return NULL;
         pty_forward_disconnect(f);
         free(f->background_color);
+        free(f->title);
         return mfree(f);
 }
 
@@ -995,3 +1013,35 @@ int pty_forward_set_background_color(PTYForward *f, const char *color) {
 
         return free_and_strdup(&f->background_color, color);
 }
+
+int pty_forward_set_title(PTYForward *f, const char *title) {
+        assert(f);
+
+        /* Refuse accepting a title when we already started shoveling */
+        if (f->out_buffer_size > 0)
+                return -EBUSY;
+
+        return free_and_strdup(&f->title, title);
+}
+
+int pty_forward_set_titlef(PTYForward *f, const char *format, ...) {
+        _cleanup_free_ char *title = NULL;
+        va_list ap;
+        int r;
+
+        assert(f);
+        assert(format);
+
+        if (f->out_buffer_size > 0)
+                return -EBUSY;
+
+        va_start(ap, format);
+        DISABLE_WARNING_FORMAT_NONLITERAL;
+        r = vasprintf(&title, format, ap);
+        REENABLE_WARNING;
+        va_end(ap);
+        if (r < 0)
+                return -ENOMEM;
+
+        return free_and_replace(f->title, title);
+}
index bae8d3591e44834b59259b568178291f90418cc4..3f0d7811a25fa300bf1b27551d830cdd793ec7ec 100644 (file)
@@ -40,5 +40,7 @@ int pty_forward_set_priority(PTYForward *f, int64_t priority);
 int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height);
 
 int pty_forward_set_background_color(PTYForward *f, const char *color);
+int pty_forward_set_title(PTYForward *f, const char *title);
+int pty_forward_set_titlef(PTYForward *f, const char *format, ...) _printf_(2,3);
 
 DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free);