Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for dumping motd on session creation #6

Merged
merged 1 commit into from
Apr 2, 2024
Merged

Conversation

ethanpailes
Copy link
Contributor

This patch adds support for one of the two motd modes that I plan to support. In this basic "dump" mode, we only display the message of the day when a user first creates a session. Since we are doing it right at the beginning, we can be confident we won't be
mangling the restore buffer. Directly injecting the message of the day into the output stream is much more fraught on reconnect.

I was hoping that this would be a simple change, but it would up being quite a bit more involved than I had hoped. The main reason for this is the interaction between the prompt prefix injection and message of the day injection. We need to make sure that motd injection happens after the prompt prefix shell code has finished executing so that it does not get clobbered, but unfortunately this is not as easy as just doing one after the other.

With the naive approach there is a race condition
where first we write the prefix injection shell code to the shell process, then we write out the message of the day, then the shell finishes processing the shell code and issues the terminal reset code emitted by the clear command at the end of the prompt prefix shell code.

To deal with this, I started scanning for the control code emitted by clear in the output stream. I was able to re-use the efficient trie I wrote for the
keybindings engine to do this.

This addresses the first part of #5, but the issue is not resolved yet. I also realized that two different config variables to control this behavior leaves too much room for weird states. In particular, I worried about doing a direct dump during reattach. I decided it is better to do everything via one variable, where the mode implies when we actually show the motd.

@ethanpailes
Copy link
Contributor Author

It turns out terminfo is WTFPL licenced, which is not allowed for google projects. I opened meh/rust-terminfo#41 asking the author to dual licence the crate to make things a bit easier. If there is no movement on that issue for a little bit I can switch to https://crates.io/crates/termini

@ethanpailes ethanpailes force-pushed the motd branch 19 times, most recently from fdb559f to 2517e9f Compare March 20, 2024 17:19
@ethanpailes
Copy link
Contributor Author

termini turns out to be slightly annoying to integrate since it does not have a clone derivation: pascalkuthe/termini#3

@ethanpailes ethanpailes force-pushed the motd branch 2 times, most recently from bc11d20 to aa0d5a0 Compare March 20, 2024 17:52
@@ -1,20 +1,14 @@
[advisories]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to add version = 2, otherwise you get all the bad old defaults.

Also, you probably want to add at the top:

[graph]
all-features = true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"#
)
} else {
return Err(anyhow!("don't know how to inject a prefix for shell '{}'", shell));
};

if needs_default_term {
script.push_str("\nclear\n");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the if/else blocks swapped? Shouldn't you set TERM if needs_default_term (term.is_none())?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, you're right, thanks

if let ClientConnectionMsg::New(conn) = &client_conn {
let chunk =
protocol::Chunk { kind: protocol::ChunkKind::Data, buf: &buf[..len] };
let mut s = conn.sink.lock().unwrap();
let write_result = chunk.write_to(&mut *s).and_then(|_| s.flush());
if let Err(err) = write_result {
info!("client_stream write err, assuming hangup: {:?}", err);
info!("client_stream write err (2), assuming hangup: {:?}", err);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the 2 about?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was to differentiate between identical log lines. I've tweaked the text for the above line so I can remove the numbers.


/// Showers know how to show the message of the day.
#[derive(Debug, Clone)]
pub struct Shower {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WDYT about "DailyMessenger" or something like that? I can't not read this is the water thing. Every. Single. Time.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah I like that. I didn't like Shower at all but wasn't quite sure what else to call it.

This patch adds support for one of the two motd modes
that I plan to support. In this basic "dump" mode,
we only display the message of the day when a user
first creates a session. Since we are doing it right
at the beginning, we can be confident we won't be
mangling the restore buffer. Directly injecting the
message of the day into the output stream is much more
fraught on reconnect.

I was hoping that this would be a simple change, but
it would up being quite a bit more involved than I
had hoped. The main reason for this is the interaction
between the prompt prefix injection and message of the
day injection. We need to make sure that motd injection
happens after the prompt prefix shell code has finished
executing so that it does not get clobbered, but unfortunately
this is not as easy as just doing one after the other.

With the naive approach there is a race condition
where first we write the prefix injection shell code to
the shell process, then we write out the message of the
day, then the shell finishes processing the shell code
and issues the terminal reset code emitted by the `clear`
command at the end of the prompt prefix shell code.

To deal with this, I started scanning for the control
code emitted by `clear` in the output stream. I was
able to re-use the efficient trie I wrote for the
keybindings engine to do this.

This addresses the first part of #5, but the issue
is not resolved yet. I also realized that two different
config variables to control this behavior leaves too much
room for weird states. In particular, I worried about
doing a direct dump during reattach. I decided it is better
to do everything via one variable, where the mode implies
when we actually show the motd.
@ethanpailes ethanpailes merged commit e94f658 into master Apr 2, 2024
4 checks passed
@ethanpailes ethanpailes deleted the motd branch April 2, 2024 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants