greetd: add terminal switch flag configuration option

This adds "switch" true/false flag in "terminal" section of
configuration file.

Flag controls whether terminal under control should be switched to
when greetd starts. If "switch" set to true, greetd behaves as it
did before, on start vt_setactivate will be called. If "switch" set
to false, and terminal under control by greetd is not currently
active VT, greetd will wait for terminal to become active with
vt_waitactive, which translates to VT_WAITACTIVE ioctl call.

* greetd/src/config/mod.rs: add "switch" flag
* greetd/src/server.rs: add using "switch" flag and waiting for active
* greetd/src/terminal/mod.rs: add vt_waitactive method
* man/greetd-5.scd: mention "switch" configuration option
This commit is contained in:
muradm
2021-08-17 01:30:45 +03:00
committed by Kenny Levinsen
parent fba10c1316
commit 87e9277654
4 changed files with 58 additions and 11 deletions

View File

@@ -35,6 +35,7 @@ pub struct ConfigInternal {
#[derive(Debug, Eq, PartialEq, Default)]
pub struct ConfigTerminal {
pub vt: VtSelection,
pub switch: bool,
}
#[derive(Debug, Eq, PartialEq)]
@@ -104,7 +105,7 @@ fn parse_old_config(config: &HashMap<&str, HashMap<&str, &str>>) -> Result<Confi
};
Ok(ConfigFile {
terminal: ConfigTerminal { vt },
terminal: ConfigTerminal { vt, switch: true },
default_session: ConfigSession {
user: greeter_user,
command: greeter,
@@ -165,6 +166,11 @@ fn parse_new_config(config: &HashMap<&str, HashMap<&str, &str>>) -> Result<Confi
.map_err(|e| format!("could not parse vt number: {}", e))?,
),
},
switch: section
.get("switch")
.unwrap_or(&"true")
.parse()
.map_err(|e| format!("could not parse switch: {}", e))?,
}),
None => Err("no terminal specified"),
}?;
@@ -300,7 +306,8 @@ greeter_user = \"greeter\"
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Specific(1)
vt: VtSelection::Specific(1),
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -322,7 +329,8 @@ greeter = \"agreety\"
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Next
vt: VtSelection::Next,
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -349,7 +357,8 @@ command = \"agreety\"
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Specific(1)
vt: VtSelection::Specific(1),
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -376,7 +385,8 @@ user = \"john\"
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Specific(1)
vt: VtSelection::Specific(1),
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -406,7 +416,8 @@ runfile = \"/path/to/greetd.state\"
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Specific(1)
vt: VtSelection::Specific(1),
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -447,7 +458,8 @@ vt = 1
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Specific(1)
vt: VtSelection::Specific(1),
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -469,7 +481,8 @@ vt = next
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Next
vt: VtSelection::Next,
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),
@@ -491,7 +504,8 @@ vt = current
config,
ConfigFile {
terminal: ConfigTerminal {
vt: VtSelection::Current
vt: VtSelection::Current,
switch: true,
},
default_session: ConfigSession {
command: "agreety".to_string(),

View File

@@ -31,6 +31,17 @@ fn reset_vt(term_mode: &TerminalMode) -> Result<(), Error> {
Ok(())
}
fn wait_vt(term_mode: &TerminalMode) -> Result<(), Error> {
match term_mode {
TerminalMode::Terminal { path, vt, .. } => {
let term = Terminal::open(path)?;
term.vt_waitactive(*vt)?;
}
TerminalMode::Stdin => (),
}
Ok(())
}
fn wrap_result<T>(res: Result<T, Error>) -> Response {
match res {
Ok(_) => Response::Success,
@@ -145,14 +156,14 @@ fn get_tty(config: &Config) -> Result<TerminalMode, Error> {
TerminalMode::Terminal {
path: format!("/dev/tty{}", vt),
vt,
switch: true,
switch: config.file.terminal.switch,
}
}
VtSelection::None => TerminalMode::Stdin,
VtSelection::Specific(vt) => TerminalMode::Terminal {
path: format!("/dev/tty{}", vt),
vt,
switch: true,
switch: config.file.terminal.switch,
},
};
return Ok(term);
@@ -215,6 +226,10 @@ pub async fn main(config: Config) -> Result<(), Error> {
let term_mode = get_tty(&config)?;
if !config.file.terminal.switch {
wait_vt(&term_mode).map_err(|e| format!("unable to wait VT: {}", e))?;
}
let ctx = Rc::new(Context::new(
config.file.default_session.command,
config.file.default_session.user,

View File

@@ -111,6 +111,14 @@ impl Terminal {
Ok(())
}
/// Waits for specified VT to become active.
pub fn vt_waitactive(&self, target_vt: usize) -> Result<(), Error> {
if let Err(v) = unsafe { ioctl::vt_waitactive(self.fd, target_vt as i32) } {
return Err(format!("terminal: unable to wait for activation: {}", v).into());
}
Ok(())
}
/// Set the VT mode to VT_AUTO with everything cleared.
fn vt_mode_clean(&self) -> Result<(), Error> {
let mode = ioctl::vt_mode {

View File

@@ -37,6 +37,16 @@ This section contains terminal configuration.
Use of a specific VT with appropriate conflict avoidance is recommended.
*switch* = true|false
Whether or not to switch to *vt*.
If set to false and *vt* is not currently active VT, greetd will wait for
*vt* to become active, before doing anything including starting greeter.
If set to true, greetd will switch current VT to *vt*,
Default is true.
## general
This section contains general configuration that does not fit in other sections