Skip to content

Commit

Permalink
add support for dumping motd on session creation
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ethanpailes committed Mar 20, 2024
1 parent 510817b commit bc11d20
Show file tree
Hide file tree
Showing 25 changed files with 859 additions and 245 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: moonrepo/setup-rust@v1
- uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f
with:
channel: '1.74.0'
bins: cargo-deny
- run: sudo apt-get install libpam0g-dev
- run: cargo deny --all-features check

postsubmit:
Expand Down
25 changes: 15 additions & 10 deletions .github/workflows/presubmit.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
name: presubmit
on: [push, pull_request, workflow_call, workflow_dispatch]
on: [pull_request, workflow_call, workflow_dispatch]

jobs:
test:
name: cargo test --all-features
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: moonrepo/setup-rust@v1
- uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f
with:
channel: '1.74.0'
- run: sudo apt-get install zsh fish
- run: cargo test --all-features
- uses: actions/upload-artifact@v4
- run: sudo apt-get install zsh fish libpam0g-dev
- run: SHPOOL_LEAVE_TEST_LOGS=true cargo test --all-features
- name: Archive Logs
if: always()
uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: test-logs
path: /tmp/shpool-test*/*.log

# miri does not handle all the IO we do, disabled for now.
#
#
# miri:
# name: cargo +nightly miri test
# runs-on: ubuntu-22.04
Expand All @@ -36,32 +39,34 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: moonrepo/setup-rust@v1
- uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f
with:
components: rustfmt
channel: nightly
- run: sudo apt-get install libpam0g-dev
- run: cargo +nightly fmt -- --check

cranky:
name: cargo +nightly cranky --all-targets -- -D warnings
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: moonrepo/setup-rust@v1
- uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f
with:
components: clippy
bins: [email protected]
channel: nightly
- run: sudo apt-get install zsh fish
- run: sudo apt-get install zsh fish libpam0g-dev
- run: cargo +nightly cranky --all-targets -- -D warnings

deny:
name: cargo deny --all-features check licenses
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- uses: moonrepo/setup-rust@v1
- uses: moonrepo/setup-rust@b8edcc56aab474d90c7cf0bb8beeaf8334c15e9f
with:
channel: '1.74.0'
bins: cargo-deny
- run: sudo apt-get install libpam0g-dev
- run: cargo deny --all-features check licenses
119 changes: 119 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
[advisories]
db-path = "~/.cargo/advisory-db"
db-urls = ["https://github.com/rustsec/advisory-db"]
vulnerability = "deny"
unmaintained = "deny"
yanked = "deny"
notice = "deny"
ignore = [
]

[licenses]
unlicensed = "deny"
allow = [
"Apache-2.0",
"MIT",
"Unicode-DFS-2016",
]
copyleft = "deny"
default = "deny"
confidence-threshold = 1.0
2 changes: 2 additions & 0 deletions libshpool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ tracing = "0.1" # logging and performance monitoring facade
bincode = "1" # serialization for the control protocol
shpool_vt100 = "0.1.2" # terminal emulation for the scrollback buffer
shell-words = "1" # parsing the -c/--cmd argument
motd = "0.2.0" # getting the message-of-the-day
termini = "1.0.0" # terminfo database

[dependencies.tracing-subscriber]
version = "0.3"
Expand Down
11 changes: 11 additions & 0 deletions libshpool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,14 @@ to an internal google version of the tool, but don't believe
that telemetry belongs in an open-source tool. Other potential
use-cases such as incorporating a shpool daemon into an
IDE that hosts remote terminals could be imagined though.

## Integrating

In order to call libshpool, you must keep a few things in mind.
In spirit, you just need to call `libshpool::run(libshpoo::Args::parse())`,
but you need to take care of a few things manually.

1. Handle the `version` subcommand. Since libshpool is a library, the output
will not be very good if the library handles the versioning.
2. Depend on the `motd` crate and call `motd::handle_reexec()` in your `main`
function.
40 changes: 40 additions & 0 deletions libshpool/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,21 @@ pub struct Config {
/// verbatim except that the string '$SHPOOL_SESSION_NAME' will
/// get replaced with the actual name of the shpool session.
pub prompt_prefix: Option<String>,

/// Control when and how shpool will display the message of the day.
pub motd: Option<MotdDisplayMode>,

/// Override arguments to pass to pam_motd.so when resolving the
/// message of the day. Normally, you want to leave this blank
/// so that shpool will scrape the default arguments used in
/// `/etc/pam.d/{ssh,login}` which typically produces the expected
/// result, but in some cases you may need to override the argument
/// list. You can also use this to make a custom message of the
/// day that is only displayed when using shpool.
///
/// See https://man7.org/linux/man-pages/man8/pam_motd.8.html
/// for more info.
pub motd_args: Option<Vec<String>>,
}

#[derive(Deserialize, Debug, Clone)]
Expand Down Expand Up @@ -140,6 +155,31 @@ pub enum SessionRestoreMode {
Lines(u16),
}

#[derive(Deserialize, Debug, Clone, Default)]
#[serde(rename_all = "lowercase")]
pub enum MotdDisplayMode {
/// Never display the message of the day.
#[default]
Never,

/// Display the message of the day using the given program
/// as the pager. The pager will be invoked like `pager /tmp/motd.txt`,
/// and normal connection will only proceed once the pager has
/// exited.
///
/// Display the message of the day each time a user attaches
/// (wether to a new session or reattaching to an existing session).
///
/// `less` by default.
// Pager(String),

/// Just dump the message of the day directly to the screen.
/// Dumps are only performed when a new session is created.
/// There is no safe way to dump directly when reattaching,
/// so we don't attempt it.
Dump,
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
Loading

0 comments on commit bc11d20

Please sign in to comment.