From 781c8c3f72f72eb19313e536b6f5622b6756d236 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 17 Dec 2024 15:37:10 +0900 Subject: [PATCH 1/6] ptyfwd: coding style fix - replace 'type *func()' -> 'type* func()', - rename output argument to 'ret'. --- src/shared/ptyfwd.c | 10 +++++----- src/shared/ptyfwd.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 00450ca6967..86ebb497dda 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -243,7 +243,7 @@ static bool drained(PTYForward *f) { return true; } -static char *background_color_sequence(PTYForward *f) { +static char* background_color_sequence(PTYForward *f) { assert(f); assert(f->background_color); @@ -960,7 +960,7 @@ int pty_forward_new( return 0; } -PTYForward *pty_forward_free(PTYForward *f) { +PTYForward* pty_forward_free(PTYForward *f) { if (!f) return NULL; @@ -972,14 +972,14 @@ PTYForward *pty_forward_free(PTYForward *f) { return mfree(f); } -int pty_forward_get_last_char(PTYForward *f, char *ch) { +int pty_forward_get_last_char(PTYForward *f, char *ret) { assert(f); - assert(ch); + assert(ret); if (!f->last_char_set) return -ENXIO; - *ch = f->last_char; + *ret = f->last_char; return 0; } diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index b86027e9bc5..ad020a7ced0 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -25,10 +25,10 @@ typedef enum PTYForwardFlags { typedef int (*PTYForwardHandler)(PTYForward *f, int rcode, void *userdata); -int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **f); -PTYForward *pty_forward_free(PTYForward *f); +int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **ret); +PTYForward* pty_forward_free(PTYForward *f); -int pty_forward_get_last_char(PTYForward *f, char *ch); +int pty_forward_get_last_char(PTYForward *f, char *ret); int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup); bool pty_forward_get_ignore_vhangup(PTYForward *f); From 5e6a48bf99d2adb3c9d22414197a593f2aa8a121 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 18 Dec 2024 11:06:07 +0900 Subject: [PATCH 2/6] ptyfwd: do not forward partial escape sequence Otherwise, if the sender is killed while writing escape sequence, we may get spurious output. --- src/shared/ptyfwd.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 86ebb497dda..f41b525b471 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -89,6 +89,8 @@ struct PTYForward { char in_buffer[LINE_MAX], *out_buffer; size_t out_buffer_size; size_t in_buffer_full, out_buffer_full; + size_t out_buffer_write_len; /* The length of the output in the buffer except for the trailing + * truncated OSC, CSI, or some (but not all) ESC sequence. */ usec_t escape_timestamp; unsigned escape_counter; @@ -151,6 +153,7 @@ static void pty_forward_disconnect(PTYForward *f) { f->out_buffer = mfree(f->out_buffer); f->out_buffer_size = 0; f->out_buffer_full = 0; + f->out_buffer_write_len = 0; f->in_buffer_full = 0; f->csi_sequence = mfree(f->csi_sequence); @@ -277,6 +280,9 @@ static int insert_background_color(PTYForward *f, size_t offset) { assert(f); + if (FLAGS_SET(f->flags, PTY_FORWARD_DUMB_TERMINAL)) + return 0; + if (!f->background_color) return 0; @@ -359,6 +365,9 @@ static int is_csi_background_reset_sequence(const char *seq) { static int insert_background_fix(PTYForward *f, size_t offset) { assert(f); + if (FLAGS_SET(f->flags, PTY_FORWARD_DUMB_TERMINAL)) + return 0; + if (!f->background_color) return 0; @@ -391,6 +400,9 @@ bool shall_set_terminal_title(void) { static int insert_window_title_fix(PTYForward *f, size_t offset) { assert(f); + if (FLAGS_SET(f->flags, PTY_FORWARD_DUMB_TERMINAL)) + return 0; + if (!f->title_prefix) return 0; @@ -414,12 +426,6 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) { assert(f); assert(offset <= f->out_buffer_full); - if (!f->background_color && !f->title_prefix) - return 0; - - if (FLAGS_SET(f->flags, PTY_FORWARD_DUMB_TERMINAL)) - return 0; - for (size_t i = offset; i < f->out_buffer_full; i++) { char c = f->out_buffer[i]; @@ -545,6 +551,9 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) { default: assert_not_reached(); } + + if (f->ansi_color_state == ANSI_COLOR_STATE_TEXT) + f->out_buffer_write_len = i + 1; } return 0; @@ -579,7 +588,7 @@ static int do_shovel(PTYForward *f) { } if (f->out_buffer) { - f->out_buffer_full = strlen(f->out_buffer); + f->out_buffer_full = f->out_buffer_write_len = strlen(f->out_buffer); f->out_buffer_size = MALLOC_SIZEOF_SAFE(f->out_buffer); } } @@ -679,9 +688,10 @@ static int do_shovel(PTYForward *f) { } } - if (f->stdout_writable && f->out_buffer_full > 0) { + if (f->stdout_writable && f->out_buffer_write_len > 0) { + assert(f->out_buffer_write_len <= f->out_buffer_full); - k = write(f->output_fd, f->out_buffer, f->out_buffer_full); + k = write(f->output_fd, f->out_buffer, f->out_buffer_write_len); if (k < 0) { if (errno == EAGAIN) @@ -700,9 +710,10 @@ static int do_shovel(PTYForward *f) { f->last_char_set = true; } - assert(f->out_buffer_full >= (size_t) k); + assert(f->out_buffer_write_len >= (size_t) k); memmove(f->out_buffer, f->out_buffer + k, f->out_buffer_full - k); f->out_buffer_full -= k; + f->out_buffer_write_len -= k; } } } @@ -711,7 +722,7 @@ static int do_shovel(PTYForward *f) { /* Exit the loop if any side hung up and if there's * nothing more to write or nothing we could write. */ - if ((f->out_buffer_full <= 0 || f->stdout_hangup) && + if ((f->out_buffer_write_len <= 0 || f->stdout_hangup) && (f->in_buffer_full <= 0 || f->master_hangup)) return pty_forward_done(f, 0); } From d517427dff319eb0735d24197e945dd99e4e44b1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 18 Dec 2024 11:10:47 +0900 Subject: [PATCH 3/6] ptyfwd: save the last character before the escape sequence If we write e.g. a line break and CSI sequence, then it is not necessary to write another line break on exit. --- src/shared/ptyfwd.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index f41b525b471..9fc8e30b0c0 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -85,6 +85,7 @@ struct PTYForward { bool last_char_set:1; char last_char; + char last_char_safe; char in_buffer[LINE_MAX], *out_buffer; size_t out_buffer_size; @@ -439,8 +440,11 @@ static int pty_forward_ansi_process(PTYForward *f, size_t offset) { if (r < 0) return r; i += r; + f->last_char_safe = c; } else if (c == 0x1B) /* ESC */ f->ansi_color_state = ANSI_COLOR_STATE_ESC; + else if (!char_is_cc(c)) + f->last_char_safe = c; break; case ANSI_COLOR_STATE_ESC: @@ -705,8 +709,15 @@ static int do_shovel(PTYForward *f) { } else { - if (k > 0) { - f->last_char = f->out_buffer[k-1]; + if (k > 0 && f->last_char_safe != '\0') { + if ((size_t) k == f->out_buffer_write_len) + /* If we wrote all, then save the last safe character. */ + f->last_char = f->last_char_safe; + else + /* If we wrote partially, then tentatively save the last written character. + * Hopefully, we will write more in the next loop. */ + f->last_char = f->out_buffer[k-1]; + f->last_char_set = true; } From 4a4e7ec0e99e7f7004bf5cdcd1c715785ff16311 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 18 Dec 2024 11:12:57 +0900 Subject: [PATCH 4/6] ptyfwd: always write additional line break on stop Currently we do that in the user of PTY forwarder, e.g. nspawn. But, let's do that unconditionally in the PTY forwarder. --- src/machine/machinectl.c | 6 ------ src/nspawn/nspawn.c | 9 +-------- src/run/run.c | 8 -------- src/shared/ptyfwd.c | 24 +++++++++++++----------- src/shared/ptyfwd.h | 2 -- 5 files changed, 14 insertions(+), 35 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 7843b9aa630..1f477e682b4 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1212,7 +1212,6 @@ static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *r } static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) { - char last_char = 0; bool machine_died; int r; @@ -1239,17 +1238,12 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - pty_forward_get_last_char(*forward, &last_char); - machine_died = (flags & PTY_FORWARD_IGNORE_VHANGUP) && pty_forward_get_ignore_vhangup(*forward) == 0; *forward = pty_forward_free(*forward); - if (last_char != '\n') - fputc('\n', stdout); - if (!arg_quiet) { if (machine_died) log_info("Machine %s terminated.", name); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index ec3bb40c3da..ee04ef8a2b6 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5740,16 +5740,9 @@ static int run_container( if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - if (forward) { - char last_char = 0; - - (void) pty_forward_get_last_char(forward, &last_char); + if (forward) forward = pty_forward_free(forward); - if (!arg_quiet && last_char != '\n') - putc('\n', stdout); - } - /* Kill if it is not dead yet anyway */ if (!arg_register && !arg_keep_unit && bus) terminate_scope(bus, arg_machine); diff --git a/src/run/run.c b/src/run/run.c index e989934c741..6a50b40c159 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -2094,14 +2094,6 @@ static int start_transient_service(sd_bus *bus) { if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - if (c.forward) { - char last_char = 0; - - r = pty_forward_get_last_char(c.forward, &last_char); - if (r >= 0 && !arg_quiet && last_char != '\n') - fputc('\n', stdout); - } - if (arg_wait && !arg_quiet) { /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, with its diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 9fc8e30b0c0..401ff8fce58 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -136,6 +136,19 @@ static void pty_forward_disconnect(PTYForward *f) { (void) loop_write(f->output_fd, ANSI_WINDOW_TITLE_POP, SIZE_MAX); } + if (f->last_char_set && f->last_char != '\n') { + const char *s; + + if (isatty_safe(f->output_fd) && f->last_char != '\r') + s = "\r\n"; + else + s = "\n"; + (void) loop_write(f->output_fd, s, SIZE_MAX); + + f->last_char_set = true; + f->last_char = '\n'; + } + if (f->close_output_fd) f->output_fd = safe_close(f->output_fd); } @@ -994,17 +1007,6 @@ PTYForward* pty_forward_free(PTYForward *f) { return mfree(f); } -int pty_forward_get_last_char(PTYForward *f, char *ret) { - assert(f); - assert(ret); - - if (!f->last_char_set) - return -ENXIO; - - *ret = f->last_char; - return 0; -} - int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) { int r; diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index ad020a7ced0..aae8b0b57ac 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -28,8 +28,6 @@ typedef int (*PTYForwardHandler)(PTYForward *f, int rcode, void *userdata); int pty_forward_new(sd_event *event, int master, PTYForwardFlags flags, PTYForward **ret); PTYForward* pty_forward_free(PTYForward *f); -int pty_forward_get_last_char(PTYForward *f, char *ret); - int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup); bool pty_forward_get_ignore_vhangup(PTYForward *f); From 12807b5a49d1fe60434d473afe11ff81a4c92306 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 18 Dec 2024 11:14:06 +0900 Subject: [PATCH 5/6] ptyfwd: always flush buffer and disconnect before exit Then, it is not necessary to manually drain PTY forwarder by the user side. Also, not necessary to free PTY forwarder earlier explicitly to make it disconnected. --- src/machine/machinectl.c | 2 -- src/nspawn/nspawn.c | 3 -- src/run/run.c | 14 +-------- src/shared/ptyfwd.c | 63 ++++++++++++++++++++++------------------ src/shared/ptyfwd.h | 4 --- 5 files changed, 36 insertions(+), 50 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 1f477e682b4..97a9129ccd7 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1242,8 +1242,6 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT (flags & PTY_FORWARD_IGNORE_VHANGUP) && pty_forward_get_ignore_vhangup(*forward) == 0; - *forward = pty_forward_free(*forward); - if (!arg_quiet) { if (machine_died) log_info("Machine %s terminated.", name); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index ee04ef8a2b6..d465cd58e25 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5740,9 +5740,6 @@ static int run_container( if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - if (forward) - forward = pty_forward_free(forward); - /* Kill if it is not dead yet anyway */ if (!arg_register && !arg_keep_unit && bus) terminate_scope(bus, arg_machine); diff --git a/src/run/run.c b/src/run/run.c index 6a50b40c159..72f8affc2dd 100644 --- a/src/run/run.c +++ b/src/run/run.c @@ -1555,16 +1555,9 @@ static int run_context_reconnect(RunContext *c) { } static void run_context_check_done(RunContext *c) { - bool done; - assert(c); - done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job; - - if (c->forward && !pty_forward_is_done(c->forward) && done) /* If the service is gone, it's time to drain the output */ - done = pty_forward_drain(c->forward); - - if (done) + if (STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job) (void) sd_event_exit(c->event, EXIT_SUCCESS); } @@ -2096,11 +2089,6 @@ static int start_transient_service(sd_bus *bus) { if (arg_wait && !arg_quiet) { - /* Explicitly destroy the PTY forwarder, so that the PTY device is usable again, with its - * original settings (i.e. proper line breaks), so that we can show the summary in a pretty - * way. */ - c.forward = pty_forward_free(c.forward); - if (!isempty(c.result)) log_info("Finished with result: %s", strna(c.result)); diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 401ff8fce58..ea365300419 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -58,8 +58,8 @@ struct PTYForward { sd_event_source *stdin_event_source; sd_event_source *stdout_event_source; sd_event_source *master_event_source; - sd_event_source *sigwinch_event_source; + sd_event_source *exit_event_source; struct termios saved_stdin_attr; struct termios saved_stdout_attr; @@ -81,7 +81,6 @@ struct PTYForward { bool read_from_master:1; bool done:1; - bool drain:1; bool last_char_set:1; char last_char; @@ -117,9 +116,9 @@ static void pty_forward_disconnect(PTYForward *f) { f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); - f->master_event_source = sd_event_source_unref(f->master_event_source); f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); + f->exit_event_source = sd_event_source_unref(f->exit_event_source); f->event = sd_event_unref(f->event); if (f->output_fd >= 0) { @@ -751,11 +750,6 @@ static int do_shovel(PTYForward *f) { return pty_forward_done(f, 0); } - /* If we were asked to drain, and there's nothing more to handle from the master, then call the callback - * too. */ - if (f->drain && drained(f)) - return pty_forward_done(f, 0); - return 0; } @@ -830,6 +824,33 @@ static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo * return 0; } +static int on_exit_event(sd_event_source *e, void *userdata) { + PTYForward *f = ASSERT_PTR(userdata); + int r; + + assert(e); + assert(e == f->exit_event_source); + + /* Drain the buffer on exit. */ + + if (f->done) + return 0; + + for (unsigned trial = 0; trial < 1000; trial++) { + if (drained(f)) + return pty_forward_done(f, 0); + + r = shovel(f); + if (r < 0) + return r; + if (f->done) + return 0; + } + + /* If we could not drain, then propagate recognizable error code. */ + return pty_forward_done(f, -ELOOP); +} + int pty_forward_new( sd_event *event, int master, @@ -990,6 +1011,12 @@ int pty_forward_new( (void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch"); + r = sd_event_add_exit(f->event, &f->exit_event_source, on_exit_event, f); + if (r < 0) + return r; + + (void) sd_event_source_set_description(f->exit_event_source, "ptyfwd-exit"); + *ret = TAKE_PTR(f); return 0; @@ -1036,12 +1063,6 @@ bool pty_forward_get_ignore_vhangup(PTYForward *f) { return FLAGS_SET(f->flags, PTY_FORWARD_IGNORE_VHANGUP); } -bool pty_forward_is_done(PTYForward *f) { - assert(f); - - return f->done; -} - void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata) { assert(f); @@ -1049,20 +1070,6 @@ void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata f->userdata = userdata; } -bool pty_forward_drain(PTYForward *f) { - assert(f); - - /* Starts draining the forwarder. Specifically: - * - * - Returns true if there are no unprocessed bytes from the pty, false otherwise - * - * - Makes sure the handler function is called the next time the number of unprocessed bytes hits zero - */ - - f->drain = true; - return drained(f); -} - int pty_forward_set_priority(PTYForward *f, int64_t priority) { int r; diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index aae8b0b57ac..615e1056e88 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -31,12 +31,8 @@ PTYForward* pty_forward_free(PTYForward *f); int pty_forward_set_ignore_vhangup(PTYForward *f, bool ignore_vhangup); bool pty_forward_get_ignore_vhangup(PTYForward *f); -bool pty_forward_is_done(PTYForward *f); - void pty_forward_set_handler(PTYForward *f, PTYForwardHandler handler, void *userdata); -bool pty_forward_drain(PTYForward *f); - int pty_forward_set_priority(PTYForward *f, int64_t priority); int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height); From 64b504bde3f9e29fa66cbfb4bb3c0608e94fba77 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 18 Dec 2024 13:35:54 +0900 Subject: [PATCH 6/6] machinectl: explicitly assign PTY forwarder to sd_bus_slot No functional change, just refactoring. --- src/machine/machinectl.c | 43 +++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 97a9129ccd7..39d3f3aed82 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1188,34 +1188,29 @@ static int bind_mount(int argc, char *argv[], void *userdata) { } static int on_machine_removed(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - PTYForward ** forward = (PTYForward**) userdata; + PTYForward *forward = ASSERT_PTR(userdata); int r; assert(m); - assert(forward); - if (*forward) { - /* If the forwarder is already initialized, tell it to - * exit on the next vhangup(), so that we still flush - * out what might be queued and exit then. */ - - r = pty_forward_set_ignore_vhangup(*forward, false); - if (r >= 0) - return 0; + /* Tell the forwarder to exit on the next vhangup(), so that we still flush out what might be queued + * and exit then. */ + r = pty_forward_set_ignore_vhangup(forward, false); + if (r < 0) { + /* On error, quit immediately. */ log_error_errno(r, "Failed to set ignore_vhangup flag: %m"); + (void) sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), EXIT_FAILURE); } - /* On error, or when the forwarder is not initialized yet, quit immediately */ - sd_event_exit(sd_bus_get_event(sd_bus_message_get_bus(m)), EXIT_FAILURE); return 0; } -static int process_forward(sd_event *event, PTYForward **forward, int master, PTYForwardFlags flags, const char *name) { - bool machine_died; +static int process_forward(sd_event *event, sd_bus_slot *machine_removed_slot, int master, PTYForwardFlags flags, const char *name) { int r; assert(event); + assert(machine_removed_slot); assert(master >= 0); assert(name); @@ -1230,17 +1225,21 @@ static int process_forward(sd_event *event, PTYForward **forward, int master, PT if (r < 0) return log_error_errno(r, "Failed to enable SIGINT/SITERM handling: %m"); - r = pty_forward_new(event, master, flags, forward); + _cleanup_(pty_forward_freep) PTYForward *forward = NULL; + r = pty_forward_new(event, master, flags, &forward); if (r < 0) return log_error_errno(r, "Failed to create PTY forwarder: %m"); + /* No userdata should not set previously. */ + assert_se(!sd_bus_slot_set_userdata(machine_removed_slot, forward)); + r = sd_event_loop(event); if (r < 0) return log_error_errno(r, "Failed to run event loop: %m"); - machine_died = + bool machine_died = (flags & PTY_FORWARD_IGNORE_VHANGUP) && - pty_forward_get_ignore_vhangup(*forward) == 0; + pty_forward_get_ignore_vhangup(forward) == 0; if (!arg_quiet) { if (machine_died) @@ -1292,7 +1291,6 @@ static int parse_machine_uid(const char *spec, const char **machine, char **uid) static int login_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; int master = -1, r; @@ -1326,7 +1324,7 @@ static int login_machine(int argc, char *argv[], void *userdata) { "member='MachineRemoved'," "arg0='", machine, "'"); - r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward); + r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to request machine removal match: %m"); @@ -1338,13 +1336,12 @@ static int login_machine(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_parse_error(r); - return process_forward(event, &forward, master, PTY_FORWARD_IGNORE_VHANGUP, machine); + return process_forward(event, slot, master, PTY_FORWARD_IGNORE_VHANGUP, machine); } static int shell_machine(int argc, char *argv[], void *userdata) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(pty_forward_freep) PTYForward *forward = NULL; _cleanup_(sd_bus_slot_unrefp) sd_bus_slot *slot = NULL; _cleanup_(sd_event_unrefp) sd_event *event = NULL; int master = -1, r; @@ -1388,7 +1385,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) { "member='MachineRemoved'," "arg0='", machine, "'"); - r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, &forward); + r = sd_bus_add_match_async(bus, &slot, match, on_machine_removed, NULL, NULL); if (r < 0) return log_error_errno(r, "Failed to request machine removal match: %m"); @@ -1418,7 +1415,7 @@ static int shell_machine(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_parse_error(r); - return process_forward(event, &forward, master, 0, machine); + return process_forward(event, slot, master, /* flags = */ 0, machine); } static int normalize_nspawn_filename(const char *name, char **ret_file) {