Skip to content

Commit

Permalink
Wayland support (#84)
Browse files Browse the repository at this point in the history
* Get started on wayland support

* Add AUR installation instructions (#87)

* File overview in README (#88)

Add file overview in README

* Working Wayland
  • Loading branch information
coastalwhite committed Nov 22, 2022
1 parent 310d4b6 commit 87c9ae9
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 40 deletions.
5 changes: 3 additions & 2 deletions extra/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ hint_margin = 2
# ---------
#

# Show an option for the TTY shell when logging in as one of the environments
include_tty_shell = true
# Show an option for the TTY shell when logging in as one of the environments.
# NOTE: it is always shown when no viable options are found.
include_tty_shell = false

# Remember the selected environment after logging in for the next time
remember = true
Expand Down
2 changes: 2 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ if [ $? -ne 0 ]; then exit 1; fi

# Create lemurs directory
echo 'Step 3: Create lemurs configuration directory'
echo 'NOTE: You still have to move your X or Wayland startup into the proper directories'
$ROOT_CMD mkdir -p "/etc/lemurs/wms"
$ROOT_CMD mkdir -p "/etc/lemurs/wayland"
if [ $? -ne 0 ]; then exit 1; fi

# Copy over configuration file
Expand Down
2 changes: 1 addition & 1 deletion src/auth/pam.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use log::info;

use pam::{Authenticator, PasswordConv};

const PAM_SERVICE: &str = "login";
const PAM_SERVICE: &str = "system-login";

use pgs_files::passwd::{get_entry_by_name, PasswdEntry};

Expand Down
163 changes: 126 additions & 37 deletions src/post_login/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ mod env_variables;
mod x;

const INITRCS_FOLDER_PATH: &str = "/etc/lemurs/wms";
const WAYLAND_FOLDER_PATH: &str = "/etc/lemurs/wayland";

#[derive(Clone)]
pub enum PostLoginEnvironment {
X { xinitrc_path: String },
// Wayland { script_path: String },
Wayland { script_path: String },
Shell,
}

pub enum EnvironmentStartError {
WaylandStartError,
XSetupError(x::XSetupError),
XStartEnvError(x::XStartEnvError),
WaitingForEnv,
Expand Down Expand Up @@ -53,6 +55,51 @@ impl PostLoginEnvironment {
EnvironmentStartError::WaitingForEnv
})?;
}
PostLoginEnvironment::Wayland { script_path } => {
let uid = user_info.uid;
let gid = user_info.gid;
let groups: Vec<Gid> = get_user_groups(&user_info.name, gid)
.unwrap()
.iter()
.map(|group| Gid::from_raw(group.gid()))
.collect();

info!("Starting Wayland Session");
let wayland_cmd = unsafe {
Command::new("/bin/sh").pre_exec(move || {
// NOTE: The order here is very vital, otherwise permission errors occur
// This is basically a copy of how the nightly standard library does it.
nix::unistd::setgroups(&groups)
.and(nix::unistd::setgid(Gid::from_raw(gid)))
.and(nix::unistd::setuid(Uid::from_raw(uid)))
.map_err(|err| err.into())
})
}
.arg("-c")
.arg(&script_path)
.stdout(Stdio::null()) // TODO: Maybe this should be logged or something?
.output()
.map_err(|err| {
error!("Filling xauth file failed. Reason: {}", err);
EnvironmentStartError::WaylandStartError
})?;

match std::str::from_utf8(&wayland_cmd.stderr) {
Ok(wl_stderr) => {
if !wl_stderr.trim().is_empty() {
warn!(
"Wayland Start Up script came back with: \"\"\"\n{}\n\"\"\"",
wl_stderr.trim()
);
}
}
Err(_) => {
warn!("Failed to read Wayland Start script stderr as UTF8");
}
}

info!("Ending Wayland Session");
}
PostLoginEnvironment::Shell => {
let uid = user_info.uid;
let gid = user_info.gid;
Expand Down Expand Up @@ -96,57 +143,99 @@ impl PostLoginEnvironment {
}

pub fn get_envs(with_tty_shell: bool) -> Vec<(String, PostLoginEnvironment)> {
let found_paths = match fs::read_dir(INITRCS_FOLDER_PATH) {
Ok(paths) => paths,
Err(_) => {
return if with_tty_shell {
vec![("TTYSHELL".to_string(), PostLoginEnvironment::Shell)]
} else {
Vec::new()
}
}
};

// NOTE: Maybe we can do something smart with `with_capacity` here.
let mut envs = Vec::new();

// TODO: Add other post login environment methods
for path in found_paths {
if let Ok(path) = path {
let file_name = path.file_name().into_string();
match fs::read_dir(INITRCS_FOLDER_PATH) {
Ok(paths) => {
for path in paths {
if let Ok(path) = path {
let file_name = path.file_name().into_string();

if let Ok(file_name) = file_name {
if let Ok(metadata) = path.metadata() {
if std::os::unix::fs::MetadataExt::mode(&metadata) & 0o111 == 0 {
warn!(
if let Ok(file_name) = file_name {
if let Ok(metadata) = path.metadata() {
if std::os::unix::fs::MetadataExt::mode(&metadata) & 0o111 == 0 {
warn!(
"'{}' is not executable and therefore not added as an environment",
file_name
);

continue;
continue;
}
}

envs.push((
file_name,
PostLoginEnvironment::X {
xinitrc_path: match path.path().to_str() {
Some(p) => p.to_string(),
None => {
warn!(
"Skipped item because it was impossible to convert to string"
);
continue;
}
},
},
));
} else {
warn!("Unable to convert OSString to String");
}
} else {
warn!("Ignored errorinous path: '{}'", path.unwrap_err());
}
}
}
Err(_) => {
warn!("Failed to read from the X folder '{}'", INITRCS_FOLDER_PATH);
}
}

match fs::read_dir(WAYLAND_FOLDER_PATH) {
Ok(paths) => {
for path in paths {
if let Ok(path) = path {
let file_name = path.file_name().into_string();

envs.push((
file_name,
PostLoginEnvironment::X {
// TODO: Remove unwrap
xinitrc_path: match path.path().to_str() {
Some(p) => p.to_string(),
None => {
if let Ok(file_name) = file_name {
if let Ok(metadata) = path.metadata() {
if std::os::unix::fs::MetadataExt::mode(&metadata) & 0o111 == 0 {
warn!(
"Skipped item because it was impossible to convert to string"
);
"'{}' is not executable and therefore not added as an environment",
file_name
);

continue;
}
},
},
));
} else {
warn!("Unable to convert OSString to String");
}

envs.push((
file_name,
PostLoginEnvironment::Wayland {
script_path: match path.path().to_str() {
Some(p) => p.to_string(),
None => {
warn!(
"Skipped item because it was impossible to convert to string"
);
continue;
}
},
},
));
} else {
warn!("Unable to convert OSString to String");
}
} else {
warn!("Ignored errorinous path: '{}'", path.unwrap_err());
}
}
} else {
warn!("Ignored errorinous path: '{}'", path.unwrap_err());
}
Err(_) => {
warn!(
"Failed to read from the wayland folder '{}'",
WAYLAND_FOLDER_PATH
);
}
}

Expand Down

0 comments on commit 87c9ae9

Please sign in to comment.