mirror of
https://github.com/rosenpass/rosenpass.git
synced 2025-12-05 20:40:02 -08:00
feat(cli): Automatically generate man page
Instead of using a static one, generate it via clap_mangen. To generate the manpage run `rosenpass --generate-manpage <folder>`. Right now clap does not support flattening of generated manpages, meaning that each subcommand is explained in its own file. To add extra sections to the main file `rosenpass.1`, it's rewritten after the initial creation. Once clap support flattened Man pages, the `generate_to` call can be removed and all subcommand are added to the `rosenpass.1` file. This implementation allows downstream manpage generation to stay unchanged even after switching from multiple manpages to a flattened one. Signed-off-by: Paul Spooren <mail@aparcar.org>
This commit is contained in:
2
.github/workflows/qc.yaml
vendored
2
.github/workflows/qc.yaml
vendored
@@ -62,8 +62,6 @@ jobs:
|
|||||||
- name: Install mandoc
|
- name: Install mandoc
|
||||||
run: sudo apt-get install -y mandoc
|
run: sudo apt-get install -y mandoc
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Check rosenpass.1
|
|
||||||
run: doc/check.sh doc/rosenpass.1
|
|
||||||
- name: Check rp.1
|
- name: Check rp.1
|
||||||
run: doc/check.sh doc/rp.1
|
run: doc/check.sh doc/rp.1
|
||||||
|
|
||||||
|
|||||||
27
Cargo.lock
generated
27
Cargo.lock
generated
@@ -401,6 +401,15 @@ dependencies = [
|
|||||||
"strsim 0.11.1",
|
"strsim 0.11.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_complete"
|
||||||
|
version = "4.5.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8937760c3f4c60871870b8c3ee5f9b30771f792a7045c48bcbba999d7d6b3b8e"
|
||||||
|
dependencies = [
|
||||||
|
"clap 4.5.20",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.18"
|
version = "4.5.18"
|
||||||
@@ -428,6 +437,16 @@ version = "0.7.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_mangen"
|
||||||
|
version = "0.2.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f17415fd4dfbea46e3274fcd8d368284519b358654772afb700dc2e8d2b24eeb"
|
||||||
|
dependencies = [
|
||||||
|
"clap 4.5.20",
|
||||||
|
"roff",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cmake"
|
name = "cmake"
|
||||||
version = "0.1.51"
|
version = "0.1.51"
|
||||||
@@ -1801,12 +1820,20 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roff"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rosenpass"
|
name = "rosenpass"
|
||||||
version = "0.3.0-dev"
|
version = "0.3.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap 4.5.20",
|
"clap 4.5.20",
|
||||||
|
"clap_complete",
|
||||||
|
"clap_mangen",
|
||||||
"command-fds",
|
"command-fds",
|
||||||
"criterion",
|
"criterion",
|
||||||
"derive_builder 0.20.2",
|
"derive_builder 0.20.2",
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ rand = "0.8.5"
|
|||||||
typenum = "1.17.0"
|
typenum = "1.17.0"
|
||||||
log = { version = "0.4.22" }
|
log = { version = "0.4.22" }
|
||||||
clap = { version = "4.5.20", features = ["derive"] }
|
clap = { version = "4.5.20", features = ["derive"] }
|
||||||
|
clap_mangen = "0.2.23"
|
||||||
|
clap_complete = "4.5.29"
|
||||||
serde = { version = "1.0.210", features = ["derive"] }
|
serde = { version = "1.0.210", features = ["derive"] }
|
||||||
arbitrary = { version = "1.3.2", features = ["derive"] }
|
arbitrary = { version = "1.3.2", features = ["derive"] }
|
||||||
anyhow = { version = "1.0.89", features = ["backtrace", "std"] }
|
anyhow = { version = "1.0.89", features = ["backtrace", "std"] }
|
||||||
|
|||||||
114
doc/rosenpass.1
114
doc/rosenpass.1
@@ -1,114 +0,0 @@
|
|||||||
.Dd $Mdocdate$
|
|
||||||
.Dt ROSENPASS 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
.Nm rosenpass
|
|
||||||
.Nd builds post-quantum-secure VPNs
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Op COMMAND
|
|
||||||
.Op Ar OPTIONS ...
|
|
||||||
.Op Ar ARGS ...
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
performs cryptographic key exchanges that are secure against quantum-computers
|
|
||||||
and then outputs the keys.
|
|
||||||
These keys can then be passed to various services, such as wireguard or other
|
|
||||||
vpn services, as pre-shared-keys to achieve security against attackers with
|
|
||||||
quantum computers.
|
|
||||||
.Pp
|
|
||||||
This is a research project and quantum computers are not thought to become
|
|
||||||
practical in fewer than ten years.
|
|
||||||
If you are not specifically tasked with developing post-quantum secure systems,
|
|
||||||
you probably do not need this tool.
|
|
||||||
.Ss COMMANDS
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Ar gen-keys --secret-key <file-path> --public-key <file-path>
|
|
||||||
Generate a keypair to use in the exchange command later.
|
|
||||||
Send the public-key file to your communication partner and keep the private-key
|
|
||||||
file secret!
|
|
||||||
.It Ar exchange private-key <file-path> public-key <file-path> [ OPTIONS ] PEERS
|
|
||||||
Start a process to exchange keys with the specified peers.
|
|
||||||
You should specify at least one peer.
|
|
||||||
.Pp
|
|
||||||
Its
|
|
||||||
.Ar OPTIONS
|
|
||||||
are as follows:
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Ar listen <ip>[:<port>]
|
|
||||||
Instructs
|
|
||||||
.Nm
|
|
||||||
to listen on the specified interface and port.
|
|
||||||
By default,
|
|
||||||
.Nm
|
|
||||||
will listen on all interfaces and select a random port.
|
|
||||||
.It Ar verbose
|
|
||||||
Extra logging.
|
|
||||||
.El
|
|
||||||
.El
|
|
||||||
.Ss PEER
|
|
||||||
Each
|
|
||||||
.Ar PEER
|
|
||||||
is defined as follows:
|
|
||||||
.Qq peer public-key <file-path> [endpoint <ip>[:<port>]] [preshared-key <file-path>] [outfile <file-path>] [wireguard <dev> <peer> <extra_params>]
|
|
||||||
.Pp
|
|
||||||
Providing a
|
|
||||||
.Ar PEER
|
|
||||||
instructs
|
|
||||||
.Nm
|
|
||||||
to exchange keys with the given peer and write the resulting PSK into the given
|
|
||||||
output file.
|
|
||||||
You must either specify the outfile or wireguard output option.
|
|
||||||
.Pp
|
|
||||||
The parameters of
|
|
||||||
.Ar PEER
|
|
||||||
are as follows:
|
|
||||||
.Bl -tag -width Ds
|
|
||||||
.It Ar endpoint <ip>[:<port>]
|
|
||||||
Specifies the address where the peer can be reached.
|
|
||||||
This will be automatically updated after the first successful key exchange with
|
|
||||||
the peer.
|
|
||||||
If this is unspecified, the peer must initiate the connection.
|
|
||||||
.It Ar preshared-key <file-path>
|
|
||||||
You may specify a pre-shared key which will be mixed into the final secret.
|
|
||||||
.It Ar outfile <file-path>
|
|
||||||
You may specify a file to write the exchanged keys to.
|
|
||||||
If this option is specified,
|
|
||||||
.Nm
|
|
||||||
will write a notification to standard out every time the key is updated.
|
|
||||||
.It Ar wireguard <dev> <peer> <extra_params>
|
|
||||||
This allows you to directly specify a wireguard peer to deploy the
|
|
||||||
pre-shared-key to.
|
|
||||||
You may specify extra parameters you would pass to
|
|
||||||
.Qq wg set
|
|
||||||
besides the preshared-key parameter which is used by
|
|
||||||
.Nm .
|
|
||||||
This makes it possible to add peers entirely from
|
|
||||||
.Nm .
|
|
||||||
.El
|
|
||||||
.Sh EXIT STATUS
|
|
||||||
.Ex -std
|
|
||||||
.Sh SEE ALSO
|
|
||||||
.Xr rp 1 ,
|
|
||||||
.Xr wg 1
|
|
||||||
.Rs
|
|
||||||
.%A Karolin Varner
|
|
||||||
.%A Benjamin Lipp
|
|
||||||
.%A Wanja Zaeske
|
|
||||||
.%A Lisa Schmidt
|
|
||||||
.%D 2023
|
|
||||||
.%T Rosenpass
|
|
||||||
.%U https://rosenpass.eu/whitepaper.pdf
|
|
||||||
.Re
|
|
||||||
.Sh STANDARDS
|
|
||||||
This tool is the reference implementation of the Rosenpass protocol, as
|
|
||||||
specified within the whitepaper referenced above.
|
|
||||||
.Sh AUTHORS
|
|
||||||
Rosenpass was created by Karolin Varner, Benjamin Lipp, Wanja Zaeske,
|
|
||||||
Marei Peischl, Stephan Ajuvo, and Lisa Schmidt.
|
|
||||||
.Pp
|
|
||||||
This manual page was written by
|
|
||||||
.An Clara Engler
|
|
||||||
.Sh BUGS
|
|
||||||
The bugs are tracked at
|
|
||||||
.Lk https://github.com/rosenpass/rosenpass/issues .
|
|
||||||
@@ -47,6 +47,8 @@ env_logger = { workspace = true }
|
|||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
toml = { workspace = true }
|
toml = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
|
clap_complete = { workspace = true }
|
||||||
|
clap_mangen = { workspace = true }
|
||||||
mio = { workspace = true }
|
mio = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
zerocopy = { workspace = true }
|
zerocopy = { workspace = true }
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
use anyhow::bail;
|
|
||||||
use anyhow::Result;
|
|
||||||
use std::env;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
/// Invokes a troff compiler to compile a manual page
|
|
||||||
fn render_man(compiler: &str, man: &str) -> Result<String> {
|
|
||||||
let out = Command::new(compiler).args(["-Tascii", man]).output()?;
|
|
||||||
if !out.status.success() {
|
|
||||||
bail!("{} returned an error", compiler);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(String::from_utf8(out.stdout)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generates the manual page
|
|
||||||
fn generate_man() -> String {
|
|
||||||
// This function is purposely stupid and redundant
|
|
||||||
|
|
||||||
let man = render_man("mandoc", "./doc/rosenpass.1");
|
|
||||||
if let Ok(man) = man {
|
|
||||||
return man;
|
|
||||||
}
|
|
||||||
|
|
||||||
let man = render_man("groff", "./doc/rosenpass.1");
|
|
||||||
if let Ok(man) = man {
|
|
||||||
return man;
|
|
||||||
}
|
|
||||||
|
|
||||||
"Cannot render manual page. Please visit https://rosenpass.eu/docs/manuals/\n".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn man() {
|
|
||||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
||||||
let man = generate_man();
|
|
||||||
let path = out_dir.join("rosenpass.1.ascii");
|
|
||||||
|
|
||||||
let mut file = File::create(&path).unwrap();
|
|
||||||
file.write_all(man.as_bytes()).unwrap();
|
|
||||||
|
|
||||||
println!("cargo:rustc-env=ROSENPASS_MAN={}", path.display());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
// For now, rerun the build script on every time, as the build script
|
|
||||||
// is not very expensive right now.
|
|
||||||
println!("cargo:rerun-if-changed=./");
|
|
||||||
man();
|
|
||||||
}
|
|
||||||
@@ -41,7 +41,7 @@ pub enum BrokerInterface {
|
|||||||
|
|
||||||
/// struct holding all CLI arguments for `clap` crate to parse
|
/// struct holding all CLI arguments for `clap` crate to parse
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about)]
|
#[command(author, version, about, long_about, arg_required_else_help = true)]
|
||||||
pub struct CliArgs {
|
pub struct CliArgs {
|
||||||
/// lowest log level to show – log messages at higher levels will be omitted
|
/// lowest log level to show – log messages at higher levels will be omitted
|
||||||
#[arg(long = "log-level", value_name = "LOG_LEVEL", group = "log-level")]
|
#[arg(long = "log-level", value_name = "LOG_LEVEL", group = "log-level")]
|
||||||
@@ -80,7 +80,15 @@ pub struct CliArgs {
|
|||||||
psk_broker_spawn: bool,
|
psk_broker_spawn: bool,
|
||||||
|
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
pub command: CliCommand,
|
pub command: Option<CliCommand>,
|
||||||
|
|
||||||
|
/// Generate man page
|
||||||
|
#[clap(long, value_name = "out_dir")]
|
||||||
|
pub generate_manpage: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Generate completion file for a shell
|
||||||
|
#[clap(long, value_name = "shell")]
|
||||||
|
pub print_completions: Option<clap_complete::Shell>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliArgs {
|
impl CliArgs {
|
||||||
@@ -218,10 +226,6 @@ pub enum CliCommand {
|
|||||||
|
|
||||||
/// Validate a configuration
|
/// Validate a configuration
|
||||||
Validate { config_files: Vec<PathBuf> },
|
Validate { config_files: Vec<PathBuf> },
|
||||||
|
|
||||||
/// Show the rosenpass manpage
|
|
||||||
// TODO make this the default, but only after the manpage has been adjusted once the CLI stabilizes
|
|
||||||
Man,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CliArgs {
|
impl CliArgs {
|
||||||
@@ -236,16 +240,7 @@ impl CliArgs {
|
|||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
use CliCommand::*;
|
use CliCommand::*;
|
||||||
match &self.command {
|
match &self.command {
|
||||||
Man => {
|
Some(GenConfig { config_file, force }) => {
|
||||||
let man_cmd = std::process::Command::new("man")
|
|
||||||
.args(["1", "rosenpass"])
|
|
||||||
.status();
|
|
||||||
|
|
||||||
if !(man_cmd.is_ok() && man_cmd.unwrap().success()) {
|
|
||||||
println!(include_str!(env!("ROSENPASS_MAN")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GenConfig { config_file, force } => {
|
|
||||||
ensure!(
|
ensure!(
|
||||||
*force || !config_file.exists(),
|
*force || !config_file.exists(),
|
||||||
"config file {config_file:?} already exists"
|
"config file {config_file:?} already exists"
|
||||||
@@ -255,7 +250,7 @@ impl CliArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated - use gen-keys instead
|
// Deprecated - use gen-keys instead
|
||||||
Keygen { args } => {
|
Some(Keygen { args }) => {
|
||||||
log::warn!("The 'keygen' command is deprecated. Please use the 'gen-keys' command instead.");
|
log::warn!("The 'keygen' command is deprecated. Please use the 'gen-keys' command instead.");
|
||||||
|
|
||||||
let mut public_key: Option<PathBuf> = None;
|
let mut public_key: Option<PathBuf> = None;
|
||||||
@@ -288,12 +283,12 @@ impl CliArgs {
|
|||||||
generate_and_save_keypair(secret_key.unwrap(), public_key.unwrap())?;
|
generate_and_save_keypair(secret_key.unwrap(), public_key.unwrap())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenKeys {
|
Some(GenKeys {
|
||||||
config_file,
|
config_file,
|
||||||
public_key,
|
public_key,
|
||||||
secret_key,
|
secret_key,
|
||||||
force,
|
force,
|
||||||
} => {
|
}) => {
|
||||||
// figure out where the key file is specified, in the config file or directly as flag?
|
// figure out where the key file is specified, in the config file or directly as flag?
|
||||||
let (pkf, skf) = match (config_file, public_key, secret_key) {
|
let (pkf, skf) = match (config_file, public_key, secret_key) {
|
||||||
(Some(config_file), _, _) => {
|
(Some(config_file), _, _) => {
|
||||||
@@ -337,7 +332,7 @@ impl CliArgs {
|
|||||||
generate_and_save_keypair(skf, pkf)?;
|
generate_and_save_keypair(skf, pkf)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExchangeConfig { config_file } => {
|
Some(ExchangeConfig { config_file }) => {
|
||||||
ensure!(
|
ensure!(
|
||||||
config_file.exists(),
|
config_file.exists(),
|
||||||
"config file '{config_file:?}' does not exist"
|
"config file '{config_file:?}' does not exist"
|
||||||
@@ -351,11 +346,11 @@ impl CliArgs {
|
|||||||
Self::event_loop(config, broker_interface, test_helpers)?;
|
Self::event_loop(config, broker_interface, test_helpers)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Exchange {
|
Some(Exchange {
|
||||||
first_arg,
|
first_arg,
|
||||||
rest_of_args,
|
rest_of_args,
|
||||||
config_file,
|
config_file,
|
||||||
} => {
|
}) => {
|
||||||
let mut rest_of_args = rest_of_args.clone();
|
let mut rest_of_args = rest_of_args.clone();
|
||||||
rest_of_args.insert(0, first_arg.clone());
|
rest_of_args.insert(0, first_arg.clone());
|
||||||
let args = rest_of_args;
|
let args = rest_of_args;
|
||||||
@@ -372,7 +367,7 @@ impl CliArgs {
|
|||||||
Self::event_loop(config, broker_interface, test_helpers)?;
|
Self::event_loop(config, broker_interface, test_helpers)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Validate { config_files } => {
|
Some(Validate { config_files }) => {
|
||||||
for file in config_files {
|
for file in config_files {
|
||||||
match config::Rosenpass::load(file) {
|
match config::Rosenpass::load(file) {
|
||||||
Ok(config) => {
|
Ok(config) => {
|
||||||
@@ -386,6 +381,8 @@ impl CliArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&None => {} // calp print help if no command is given
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,13 +1,51 @@
|
|||||||
|
use clap::CommandFactory;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use clap_mangen::roff::{roman, Roff};
|
||||||
use log::error;
|
use log::error;
|
||||||
use rosenpass::cli::CliArgs;
|
use rosenpass::cli::CliArgs;
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
|
|
||||||
|
fn print_custom_man_section(section: &str, text: &str, file: &mut std::fs::File) {
|
||||||
|
let mut roff = Roff::default();
|
||||||
|
roff.control("SH", [section]);
|
||||||
|
roff.text([roman(text)]);
|
||||||
|
let _ = roff.to_writer(file);
|
||||||
|
}
|
||||||
|
|
||||||
/// Catches errors, prints them through the logger, then exits
|
/// Catches errors, prints them through the logger, then exits
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
// parse CLI arguments
|
// parse CLI arguments
|
||||||
let args = CliArgs::parse();
|
let args = CliArgs::parse();
|
||||||
|
|
||||||
|
if let Some(shell) = args.print_completions {
|
||||||
|
let mut cmd = CliArgs::command();
|
||||||
|
clap_complete::generate(shell, &mut cmd, "rosenpass", &mut std::io::stdout());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(out_dir) = args.generate_manpage {
|
||||||
|
std::fs::create_dir_all(&out_dir).expect("Failed to create man pages directory");
|
||||||
|
|
||||||
|
let cmd = CliArgs::command();
|
||||||
|
let man = clap_mangen::Man::new(cmd.clone());
|
||||||
|
let _ = clap_mangen::generate_to(cmd, &out_dir);
|
||||||
|
|
||||||
|
let file_path = out_dir.join("rosenpass.1");
|
||||||
|
let mut file = std::fs::File::create(file_path).expect("Failed to create man page file");
|
||||||
|
|
||||||
|
let _ = man.render_title(&mut file);
|
||||||
|
let _ = man.render_name_section(&mut file);
|
||||||
|
let _ = man.render_synopsis_section(&mut file);
|
||||||
|
let _ = man.render_subcommands_section(&mut file);
|
||||||
|
let _ = man.render_options_section(&mut file);
|
||||||
|
print_custom_man_section("EXIT STATUS", EXIT_STATUS_MAN, &mut file);
|
||||||
|
print_custom_man_section("SEE ALSO", SEE_ALSO_MAN, &mut file);
|
||||||
|
print_custom_man_section("STANDARDS", STANDARDS_MAN, &mut file);
|
||||||
|
print_custom_man_section("AUTHORS", AUTHORS_MAN, &mut file);
|
||||||
|
print_custom_man_section("BUGS", BUGS_MAN, &mut file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
use rosenpass_secret_memory as SM;
|
use rosenpass_secret_memory as SM;
|
||||||
#[cfg(feature = "experiment_memfd_secret")]
|
#[cfg(feature = "experiment_memfd_secret")]
|
||||||
@@ -43,3 +81,21 @@ pub fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static EXIT_STATUS_MAN: &str = r"
|
||||||
|
The rosenpass utility exits 0 on success, and >0 if an error occurs.";
|
||||||
|
|
||||||
|
static SEE_ALSO_MAN: &str = r"
|
||||||
|
rp(1), wg(1)
|
||||||
|
|
||||||
|
Karolin Varner, Benjamin Lipp, Wanja Zaeske, and Lisa Schmidt, Rosenpass, https://rosenpass.eu/whitepaper.pdf, 2023.";
|
||||||
|
|
||||||
|
static STANDARDS_MAN: &str = r"
|
||||||
|
This tool is the reference implementation of the Rosenpass protocol, as
|
||||||
|
specified within the whitepaper referenced above.";
|
||||||
|
|
||||||
|
static AUTHORS_MAN: &str = r"
|
||||||
|
Rosenpass was created by Karolin Varner, Benjamin Lipp, Wanja Zaeske, Marei
|
||||||
|
Peischl, Stephan Ajuvo, and Lisa Schmidt.";
|
||||||
|
|
||||||
|
static BUGS_MAN: &str = r"
|
||||||
|
The bugs are tracked at https://github.com/rosenpass/rosenpass/issues.";
|
||||||
|
|||||||
Reference in New Issue
Block a user