This commit is contained in:
bjorn3
2025-04-13 16:51:27 +02:00
parent 6f2514ed95
commit 6a208c6b34
13 changed files with 151 additions and 139 deletions
+6 -19
View File
@@ -120,13 +120,10 @@ pub fn getpty(columns: u32, lines: u32) -> (RawFd, String) {
.expect("getty: failed to create PTY");
if let Ok(winsize_fd) = redox::dup(master, b"winsize") {
let _ = redox::write(
winsize_fd,
&redox_termios::Winsize {
ws_row: lines as u16,
ws_col: columns as u16,
},
);
let _ = redox::write(winsize_fd, &redox_termios::Winsize {
ws_row: lines as u16,
ws_col: columns as u16,
});
let _ = redox::close(winsize_fd);
}
@@ -137,12 +134,7 @@ pub fn getpty(columns: u32, lines: u32) -> (RawFd, String) {
})
}
fn daemon(
tty_fd: RawFd,
clear: bool,
contain: bool,
stderr: &mut Stderr,
) {
fn daemon(tty_fd: RawFd, clear: bool, contain: bool, stderr: &mut Stderr) {
let (columns, lines) = {
let mut path = [0; 4096];
if let Ok(count) = redox::fpath(tty_fd as usize, &mut path) {
@@ -198,12 +190,7 @@ fn daemon(
match command.spawn() {
Ok(mut process) => {
handle(
&mut event_queue,
tty_fd,
master_fd,
&mut process,
);
handle(&mut event_queue, tty_fd, master_fd, &mut process);
}
Err(err) => fail(&format!("getty: failed to execute login: {}", err), stderr),
}
+9 -7
View File
@@ -7,7 +7,8 @@ use std::process::exit;
use redox_users::{All, AllGroups, Config, Error, GroupBuilder};
const _MAN_PAGE: &'static str = /* @MANSTART{groupadd} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{groupadd} */
r#"
NAME
groupadd - add a user group
@@ -44,7 +45,8 @@ fn main() {
(@arg GROUP: +required "Add group GROUP")
(@arg FORCE: -f --force "Force the status of the program to be 0 even if the group exists")
(@arg GID: -g --gid +takes_value "Group id. Positive integer and must not be in use")
).get_matches();
)
.get_matches();
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
@@ -58,11 +60,11 @@ fn main() {
exit(1);
}
id
},
}
None => sys_groups.get_unique_id().unwrap_or_else(|| {
eprintln!("groupadd: no available gid");
exit(1);
})
eprintln!("groupadd: no available gid");
exit(1);
}),
};
let group = GroupBuilder::new(groupname).gid(gid);
@@ -70,7 +72,7 @@ fn main() {
Ok(_) => (),
Err(Error::GroupAlreadyExists) if args.is_present("FORCE") => {
exit(0);
},
}
Err(err) => {
eprintln!("groupadd: {}", err);
exit(1);
+4 -2
View File
@@ -4,7 +4,8 @@ extern crate clap;
use extra::option::OptionalExt;
use redox_users::{All, AllGroups, Config};
const _MAN_PAGE: &'static str = /* @MANSTART{groupdel} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{groupdel} */
r#"
NAME
groupdel - modify system files to delete groups
@@ -33,7 +34,8 @@ fn main() {
(author: "Wesley Hershberger")
(about: "Removes a group from the system using redox_users")
(@arg GROUP: +required "Removes group GROUP")
).get_matches();
)
.get_matches();
let group = matches.value_of("GROUP").unwrap();
+10 -9
View File
@@ -6,7 +6,8 @@ use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config};
const _MAN_PAGE: &'static str = /* @MANSTART{groupmod} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{groupmod} */
r#"
NAME
groupmod - modify group information
@@ -45,23 +46,23 @@ fn main() {
(@arg GROUP: +required "Modify GROUP")
(@arg GID: -g --gid +takes_value "Change GROUP's group id. See man page for details")
(@arg NAME: -n --name +takes_value "Change GROUP's name")
).get_matches();
)
.get_matches();
let groupname = args.value_of("GROUP").unwrap();
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
{
let group = sys_groups
.get_mut_by_name(groupname)
.unwrap_or_else(|| {
eprintln!("groupmod: group not found: {}", groupname);
exit(1);
});
let group = sys_groups.get_mut_by_name(groupname).unwrap_or_else(|| {
eprintln!("groupmod: group not found: {}", groupname);
exit(1);
});
if let Some(gid) = args.value_of("GID") {
let gid = gid.parse::<usize>().unwrap_or_exit(1);
// Update users
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
for user in sys_users.iter_mut() {
if user.gid == group.gid {
user.gid = gid;
+13 -10
View File
@@ -5,9 +5,10 @@ use std::env::args;
use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{get_egid, get_gid, get_euid, get_uid, All, AllUsers, AllGroups, Config};
use redox_users::{All, AllGroups, AllUsers, Config, get_egid, get_euid, get_gid, get_uid};
const _MAN_PAGE: &'static str = /* @MANSTART{id} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{id} */
r#"
NAME
id - display user identity
@@ -67,7 +68,7 @@ pub fn main() {
let args = match &*args().nth(0).unwrap_or(String::new()) {
"whoami" => app.get_matches_from(["id", "-un"].iter()),
_ => app.get_matches()
_ => app.get_matches(),
};
// Display the different group IDs (effective and real)
@@ -79,16 +80,17 @@ pub fn main() {
println!("{} {}", egid, gid);
exit(0);
}
}
// Display effective/real process user ID UNIX user name
if args.is_present("USER") && args.is_present("NAME") {
// Display effective/real process user ID UNIX user name
if args.is_present("USER") && args.is_present("NAME") {
// Did they pass -r? If so, we show the real
let uid = if args.is_present("REAL") {
get_uid()
} else {
get_euid()
}.unwrap_or_exit(1);
}
.unwrap_or_exit(1);
let users = AllUsers::basic(Config::default()).unwrap_or_exit(1);
let user = users.get_by_id(uid).unwrap_or_exit(1);
@@ -113,14 +115,15 @@ pub fn main() {
exit(0);
}
// Display effective/real process group ID UNIX group name
if args.is_present("GROUP") && args.is_present("NAME") {
// Display effective/real process group ID UNIX group name
if args.is_present("GROUP") && args.is_present("NAME") {
// Did they pass -r? If so we show the real one
let gid = if args.is_present("REAL") {
get_gid()
} else {
get_egid()
}.unwrap_or_exit(1);
}
.unwrap_or_exit(1);
let groups = AllGroups::new(Config::default()).unwrap_or_exit(1);
let group = groups.get_by_id(gid).unwrap_or_exit(1);
+9 -5
View File
@@ -6,11 +6,12 @@ use std::io::{self, Write};
use std::str;
use extra::option::OptionalExt;
use termion::input::TermRead;
use redox_users::{All, AllUsers, Config};
use termion::input::TermRead;
use userutils::spawn_shell;
const _MAN_PAGE: &'static str = /* @MANSTART{login} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{login} */
r#"
NAME
login - log into the computer
@@ -39,7 +40,8 @@ pub fn main() {
let _args = clap_app!(login =>
(author: "Jeremy Soller, Jose Narvaez")
(about: "Login as a user")
).get_matches();
)
.get_matches();
if let Ok(mut issue) = File::open(ISSUE_FILE) {
io::copy(&mut issue, &mut stdout).r#try(&mut stderr);
@@ -66,7 +68,7 @@ pub fn main() {
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
continue;
},
}
Some(user) => {
if user.is_passwd_blank() {
if let Ok(mut motd) = File::open(MOTD_FILE) {
@@ -78,7 +80,9 @@ pub fn main() {
break;
}
stdout.write_all(b"\x1B[1mpassword:\x1B[0m ") .r#try(&mut stderr);
stdout
.write_all(b"\x1B[1mpassword:\x1B[0m ")
.r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if let Some(password) = stdin.read_passwd(&mut stdout).r#try(&mut stderr) {
stdout.write(b"\n").r#try(&mut stderr);
+18 -11
View File
@@ -6,10 +6,11 @@ use std::io::Write;
use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{All, AllUsers, Config, get_uid};
use termion::input::TermRead;
use redox_users::{get_uid, All, AllUsers, Config};
const _MAN_PAGE: &'static str = /* @MANSTART{passwd} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{passwd} */
r#"
NAME
passwd - modify a user's password
@@ -49,7 +50,8 @@ fn main() {
(about: "Set user passwords")
(@arg LOGIN: "Apply to login. Sets password for current user if not supplied")
(@arg LOCK: -l --lock "Lock the password for an account (no login)")
).get_matches();
)
.get_matches();
let uid = get_uid().unwrap_or_exit(1);
let mut users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
@@ -57,13 +59,13 @@ fn main() {
{
let user = match args.value_of("LOGIN") {
Some(login) => users.get_mut_by_name(login).unwrap_or_else(|| {
eprintln!("passwd: user does not exist: {}", login);
exit(1);
}),
eprintln!("passwd: user does not exist: {}", login);
exit(1);
}),
None => users.get_mut_by_id(uid).unwrap_or_else(|| {
eprintln!("passwd: you do not exist");
exit(1);
})
eprintln!("passwd: you do not exist");
exit(1);
}),
};
if args.is_present("LOCK") {
@@ -100,7 +102,9 @@ fn main() {
stdout.write(b"\nconfirm password: ").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
if let Some(confirm_password) = stdin.read_passwd(&mut stdout).r#try(&mut stderr) {
if let Some(confirm_password) =
stdin.read_passwd(&mut stdout).r#try(&mut stderr)
{
stdout.write(b"\n").r#try(&mut stderr);
stdout.flush().r#try(&mut stderr);
@@ -123,7 +127,10 @@ fn main() {
exit(1);
}
} else {
eprintln!("passwd: you do not have permission to set the password of '{}'", user.user);
eprintln!(
"passwd: you do not have permission to set the password of '{}'",
user.user
);
exit(1);
}
}
+10 -7
View File
@@ -6,11 +6,12 @@ use std::process::exit;
use std::str;
use extra::option::OptionalExt;
use redox_users::{All, AllUsers, Config, get_uid};
use termion::input::TermRead;
use redox_users::{get_uid, All, AllUsers, Config};
use userutils::spawn_shell;
const _MAN_PAGE: &'static str = /* @MANSTART{su} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{su} */
r#"
NAME
su - substitute user identity
@@ -42,11 +43,10 @@ pub fn main() {
(author: "Jeremy Soller, Jose Narvaez")
(about: "substitue user identity")
(@arg LOGIN: "Login as LOGIN. Default is \'root\'")
).get_matches();
)
.get_matches();
let target_user = args
.value_of("LOGIN")
.unwrap_or("root");
let target_user = args.value_of("LOGIN").unwrap_or("root");
let uid = get_uid().unwrap_or_exit(1);
@@ -63,7 +63,10 @@ pub fn main() {
stdout.flush().unwrap_or_exit(1);
// Read the password, reading an empty string if CTRL-d is specified
let password = stdin.read_passwd(&mut stdout).r#try(&mut stderr).unwrap_or(String::new());
let password = stdin
.read_passwd(&mut stdout)
.r#try(&mut stderr)
.unwrap_or(String::new());
writeln!(stderr, "\n").unwrap_or_exit(1);
+2 -2
View File
@@ -1,10 +1,10 @@
use std::env;
use std::io::{self, Write};
use std::os::unix::process::CommandExt;
use std::process::{exit, Command};
use std::process::{Command, exit};
use extra::option::OptionalExt;
use redox_users::{get_uid, All, AllGroups, AllUsers, Config};
use redox_users::{All, AllGroups, AllUsers, Config, get_uid};
use termion::input::TermRead;
const MAX_ATTEMPTS: u16 = 3;
+37 -41
View File
@@ -7,7 +7,8 @@ use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config, GroupBuilder, UserBuilder};
use userutils::create_user_dir;
const _MAN_PAGE: &'static str = /* @MANSTART{useradd} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{useradd} */
r#"
NAME
useradd - add a new user
@@ -105,12 +106,14 @@ fn main() {
-u --uid
+takes_value
"Set LOGIN's user id. Positive ineger and must not be in use.")
).get_matches();
)
.get_matches();
// unwrap is safe because of "+required". clap-rs is cool...
let login = args.value_of("LOGIN").unwrap();
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
let uid = match args.value_of("UID") {
@@ -121,13 +124,11 @@ fn main() {
exit(1);
}
id
},
None => sys_users
.get_unique_id()
.unwrap_or_else(|| {
eprintln!("useradd: no available uid");
exit(1);
})
}
None => sys_users.get_unique_id().unwrap_or_else(|| {
eprintln!("useradd: no available uid");
exit(1);
}),
};
let gid = if args.is_present("NO_USER_GROUP") {
@@ -148,13 +149,11 @@ fn main() {
exit(1);
}
id
},
None => sys_groups
.get_unique_id()
.unwrap_or_else(|| {
eprintln!("useradd: no available gid");
exit(1);
})
}
None => sys_groups.get_unique_id().unwrap_or_else(|| {
eprintln!("useradd: no available gid");
exit(1);
}),
};
sys_groups
.add_group(GroupBuilder::new(login).gid(id).user(login))
@@ -165,35 +164,32 @@ fn main() {
id
};
let gecos = args
.value_of("COMMENT")
.unwrap_or(login);
let gecos = args.value_of("COMMENT").unwrap_or(login);
//Ugly way to satisfy the borrow checker...
let mut sys_homes = String::from(DEFAULT_HOME);
let userhome = args
.value_of("HOME_DIR")
.unwrap_or_else(|| {
if args.is_present("CREATE_HOME") {
sys_homes.push_str("/");
sys_homes.push_str(&login);
sys_homes.as_str()
} else {
"/"
}
});
let userhome = args.value_of("HOME_DIR").unwrap_or_else(|| {
if args.is_present("CREATE_HOME") {
sys_homes.push_str("/");
sys_homes.push_str(&login);
sys_homes.as_str()
} else {
"/"
}
});
let shell = args
.value_of("SHELL")
.unwrap_or(DEFAULT_SHELL);
let shell = args.value_of("SHELL").unwrap_or(DEFAULT_SHELL);
let user = UserBuilder::new(login).uid(uid).gid(gid).name(gecos).home(userhome).shell(shell);
sys_users
.add_user(user)
.unwrap_or_else(|err| {
eprintln!("useradd: {}: {}", err, login);
exit(1);
});
let user = UserBuilder::new(login)
.uid(uid)
.gid(gid)
.name(gecos)
.home(userhome)
.shell(shell);
sys_users.add_user(user).unwrap_or_else(|err| {
eprintln!("useradd: {}: {}", err, login);
exit(1);
});
// Make sure to try and create the user/groups before we create
// their home, that way we get a permissions error that makes
+6 -3
View File
@@ -8,7 +8,8 @@ use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config};
use userutils::AllGroupsExt;
const _MAN_PAGE: &'static str = /* @MANSTART{userdel} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{userdel} */
r#"
NAME
userdel - modify system files to delete users
@@ -41,11 +42,13 @@ fn main() {
(about: "Removes system users using redox_users")
(@arg LOGIN: +required "Remove user LOGIN")
(@arg REMOVE: -r --remove "Remove the user's home and all files and directories inside")
).get_matches();
)
.get_matches();
let login = args.value_of("LOGIN").unwrap();
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
{
sys_groups.remove_user_from_all_groups(login);
+19 -15
View File
@@ -6,9 +6,10 @@ use std::process::exit;
use extra::option::OptionalExt;
use redox_users::{All, AllGroups, AllUsers, Config};
use userutils::{create_user_dir, AllGroupsExt};
use userutils::{AllGroupsExt, create_user_dir};
const _MAN_PAGE: &'static str = /* @MANSTART{usermod} */ r#"
const _MAN_PAGE: &'static str = /* @MANSTART{usermod} */
r#"
NAME
usermod - modify user information
@@ -116,32 +117,35 @@ fn main() {
let login = args.value_of("LOGIN").unwrap();
//TODO: Does not always need shadowfile access
let mut sys_users = AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_users =
AllUsers::authenticator(Config::default().writeable(true)).unwrap_or_exit(1);
let mut sys_groups;
if let Some(new_groups) = args.value_of("SET_GROUPS") {
sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
sys_groups.remove_user_from_all_groups(login);
sys_groups.add_user_to_groups(login, new_groups.split(',').collect()).unwrap_or_exit(1);
sys_groups
.add_user_to_groups(login, new_groups.split(',').collect())
.unwrap_or_exit(1);
sys_groups.save().unwrap_or_exit(1);
}
if let Some(new_groups) = args.value_of("APPEND_GROUPS") {
sys_groups = AllGroups::new(Config::default().writeable(true)).unwrap_or_exit(1);
sys_groups.add_user_to_groups(login, new_groups.split(',').collect()).unwrap_or_exit(1);
sys_groups
.add_user_to_groups(login, new_groups.split(',').collect())
.unwrap_or_exit(1);
sys_groups.save().unwrap_or_exit(1);
}
let uid = args
.value_of("UID")
.map(|uid| {
let uid = uid.parse::<usize>().unwrap_or_exit(1);
if let Some(_user) = sys_users.get_by_id(uid) {
eprintln!("usermod: userid already in use: {}", uid);
exit(1);
}
uid
});
let uid = args.value_of("UID").map(|uid| {
let uid = uid.parse::<usize>().unwrap_or_exit(1);
if let Some(_user) = sys_users.get_by_id(uid) {
eprintln!("usermod: userid already in use: {}", uid);
exit(1);
}
uid
});
{
let user = sys_users.get_mut_by_name(&login).unwrap_or_else(|| {
+8 -8
View File
@@ -18,10 +18,10 @@
use std::io::Result as IoResult;
use redox_users::{auth, All, AllGroups, Result, User, Error};
use libredox::call::{open, fchown};
use libredox::call::{fchown, open};
use libredox::error::Result as SysResult;
use libredox::flag::{O_CREAT, O_DIRECTORY, O_CLOEXEC};
use libredox::flag::{O_CLOEXEC, O_CREAT, O_DIRECTORY};
use redox_users::{All, AllGroups, Error, Result, User, auth};
const DEFAULT_MODE: u16 = 0o700;
@@ -38,7 +38,7 @@ impl AllGroupsExt for AllGroups {
for groupname in new_groups {
let group = match self.get_mut_by_name(groupname) {
Some(group) => group,
None => return Err(Error::UserNotFound)
None => return Err(Error::UserNotFound),
};
group.users.push(login.to_string());
}
@@ -48,8 +48,7 @@ impl AllGroupsExt for AllGroups {
/// Remove a user from all groups of which they are a member
fn remove_user_from_all_groups(&mut self, login: &str) {
for group in self.iter_mut() {
let op_pos = group.users.iter()
.position(|username| username == login );
let op_pos = group.users.iter().position(|username| username == login);
if let Some(indx) = op_pos {
group.users.remove(indx);
}
@@ -78,13 +77,14 @@ pub fn spawn_shell(user: &User<auth::Full>) -> IoResult<i32> {
let mut child = command.spawn()?;
match child.wait()?.code() {
Some(code) => Ok(code),
None => Ok(1)
None => Ok(1),
}
}
/// Creates a directory with 700 user:user permissions
pub fn create_user_dir<T>(user: &User<auth::Full>, dir: T) -> SysResult<()>
where T: AsRef<str> + std::convert::AsRef<[u8]>
where
T: AsRef<str> + std::convert::AsRef<[u8]>,
{
let fd = open(dir, O_CREAT | O_DIRECTORY | O_CLOEXEC, DEFAULT_MODE)?;
fchown(fd, user.uid as u32, user.gid as u32)?;